refactor: Dart based Github Workflow CLI (#1490)

* feat: add build dart script for windows

* feat: add android build support

* feat: add linux build support

* feat: add macos build support

* feat: add ios build support

* feat: add deps install command and workflow file

* cd: what?

* cd: what?

* cd: what?

* cd: update workflow inputs

* cd: replace release binary

* cd: run flutter pub get

* cd: use dpkg zstd instead of xz, windows disable innoInstall, fix channel enum.name and reset pubspec after changing build no for nightly

* cd: fix tar copy path

* cd: fix copy linux command

* cd: fix windows inno depend and fix android aab path

* cd: idk

* cd: linux why???

* cd: windows choco copy failed

* cd: use dart tar archive for creating tar file

* cd: fix linux file copy error

* cd: use tar command directly

* feat: add linux_arm platform

* cd: add linux_arm platform

* cd: don't know what?

* feat: notification about nightly channel update

* chore: fix some errors parsing nightly version info
This commit is contained in:
Kingkor Roy Tirtho 2024-05-09 15:26:58 +06:00 committed by GitHub
parent 4ca893950b
commit a77b6776e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
24 changed files with 837 additions and 532 deletions

View File

@ -9,3 +9,6 @@ ENABLE_UPDATE_CHECK=
LASTFM_API_KEY= LASTFM_API_KEY=
LASTFM_API_SECRET= LASTFM_API_SECRET=
# Release channel. Can be: nightly, stable
RELEASE_CHANNEL=

8
.github/Dockerfile vendored
View File

@ -10,14 +10,10 @@ COPY . .
RUN chown -R $(whoami) /app RUN chown -R $(whoami) /app
RUN flutter pub get &&\ RUN flutter pub get
flutter config --enable-linux-desktop &&\
flutter pub get &&\
dart run build_runner build --delete-conflicting-outputs
RUN alias dpkg-deb="dpkg-deb --Zxz" &&\ RUN alias dpkg-deb="dpkg-deb --Zxz" &&\
flutter_distributor package --platform=linux --targets=deb flutter_distributor package --platform=linux --targets=deb --skip-clean
RUN make tar VERSION=${BUILD_VERSION} ARCH=arm64 PKG_ARCH=aarch64 RUN make tar VERSION=${BUILD_VERSION} ARCH=arm64 PKG_ARCH=aarch64

View File

@ -2,296 +2,65 @@ name: Spotube Release Binary
on: on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version:
description: Version to release (x.x.x)
default: 3.6.0
required: true
channel: channel:
type: choice type: choice
description: Release Channel
required: true
options: options:
- stable - stable
- nightly - nightly
default: nightly default: nightly
description: The release channel
debug: debug:
description: Debug on failed when channel is nightly
required: true
type: boolean type: boolean
default: false default: false
description: Debug with SSH toggle
required: false
dry_run: dry_run:
description: Dry run
required: true
type: boolean type: boolean
default: true default: false
description: Dry run without uploading to release
env: env:
FLUTTER_VERSION: '3.19.5' FLUTTER_VERSION: 3.19.5
permissions:
contents: write
jobs: jobs:
windows: build_platform:
runs-on: windows-latest strategy:
steps: matrix:
- uses: actions/checkout@v4 include:
- uses: subosito/flutter-action@v2.12.0 - os: ubuntu-latest
with: platform: linux
cache: true files: |
flutter-version: ${{ env.FLUTTER_VERSION }} dist/Spotube-linux-x86_64.deb
dist/Spotube-linux-x86_64.rpm
- name: Replace pubspec version and BUILD_VERSION Env (nightly) dist/spotube-linux-*-x86_64.tar.xz
if: ${{ inputs.channel == 'nightly' }} - os: ubuntu-latest
run: | platform: linux_arm
choco install sed make yq -y files: |
yq -i '.version |= sub("\+\d+", "-${{ inputs.channel }}+")' pubspec.yaml dist/Spotube-linux-aarch64.deb
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml dist/spotube-linux-*-aarch64.tar.xz
echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV - os: ubuntu-latest
shell: bash platform: android
files: |
- name: BUILD_VERSION Env (stable) build/Spotube-android-all-arch.apk
if: ${{ inputs.channel == 'stable' }} build/Spotube-playstore-all-arch.aab
run: | - os: windows-latest
"BUILD_VERSION=${{ inputs.version }}" >> $env:GITHUB_ENV platform: windows
files: |
- name: Replace version in files dist/Spotube-windows-x86_64.nupkg
run: | dist/Spotube-windows-x86_64-setup.exe
choco install sed make -y - os: macos-latest
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ env.BUILD_VERSION }}/" windows/runner/Runner.rc platform: ios
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ env.BUILD_VERSION }}/" choco-struct/tools/VERIFICATION.txt files: |
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ env.BUILD_VERSION }}/" choco-struct/spotube.nuspec Spotube-iOS.ipa
- os: macos-14
- name: Create Stable .env platform: macos
if: ${{ inputs.channel == 'stable' }} files: |
run: echo '${{ secrets.DOTENV_RELEASE }}' > .env build/Spotube-macos-universal.dmg
build/Spotube-macos-universal.pkg
- name: Create Nightly .env runs-on: ${{matrix.os}}
if: ${{ inputs.channel == 'nightly' }}
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- name: Generating Secrets
run: |
flutter config --enable-windows-desktop
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Build Windows Executable
run: |
dart pub global activate flutter_distributor
make innoinstall
flutter_distributor package --platform=windows --targets=exe --skip-clean
mv dist/**/spotube-*-windows-setup.exe dist/Spotube-windows-x86_64-setup.exe
- name: Create Chocolatey Package and set hash
if: ${{ inputs.channel == 'stable' }}
run: |
Set-Variable -Name HASH -Value (Get-FileHash dist\Spotube-windows-x86_64-setup.exe).Hash
sed -i "s/%{{WIN_SHA256}}%/$HASH/" choco-struct/tools/VERIFICATION.txt
make choco
mv dist/spotube.*.nupkg dist/Spotube-windows-x86_64.nupkg
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
dist/Spotube-windows-x86_64.nupkg
dist/Spotube-windows-x86_64-setup.exe
- name: Debug With SSH When fails
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2.12.0
with:
cache: true
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
- name: Install Dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse libunwind-dev locate patchelf gir1.2-appindicator3-0.1 libappindicator3-1 libappindicator3-dev libsecret-1-0 libjsoncpp25 libsecret-1-dev libjsoncpp-dev libnotify-bin libnotify-dev mpv libmpv-dev
- name: Install AppImage Tool
run: |
wget -O appimagetool "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod +x appimagetool
mv appimagetool /usr/local/bin/
- name: Replace pubspec version and BUILD_VERSION Env (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: |
curl -sS https://webi.sh/yq | sh
yq -i '.version |= sub("\+\d+", "+${{ inputs.channel }}.")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV
- name: BUILD_VERSION Env (stable)
if: ${{ inputs.channel == 'stable' }}
run: |
echo "BUILD_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
- name: Create Stable .env
if: ${{ inputs.channel == 'stable' }}
run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
- name: Create Nightly .env
if: ${{ inputs.channel == 'nightly' }}
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- name: Replace Version in files
run: |
sed -i 's|%{{APPDATA_RELEASE}}%|<release version="${{ env.BUILD_VERSION }}" date="${{ steps.date.outputs.date }}" />|' linux/com.github.KRTirtho.Spotube.appdata.xml
- name: Generate Secrets
run: |
flutter config --enable-linux-desktop
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Build Linux Packages
run: |
dart pub global activate flutter_distributor
alias dpkg-deb="dpkg-deb --Zxz"
flutter_distributor package --platform=linux --targets=deb
flutter_distributor package --platform=linux --targets=rpm
- name: Create tar.xz (stable)
if: ${{ inputs.channel == 'stable' }}
run: make tar VERSION=${{ env.BUILD_VERSION }} ARCH=x64 PKG_ARCH=x86_64
- name: Create tar.xz (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: make tar VERSION=nightly ARCH=x64 PKG_ARCH=x86_64
- name: Move Files to dist
run: |
mv build/spotube-linux-*-x86_64.tar.xz dist/
mv dist/**/spotube-*-linux.deb dist/Spotube-linux-x86_64.deb
mv dist/**/spotube-*-linux.rpm dist/Spotube-linux-x86_64.rpm
- uses: actions/upload-artifact@v3
if: ${{ inputs.channel == 'stable' }}
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
dist/Spotube-linux-x86_64.deb
dist/Spotube-linux-x86_64.rpm
dist/spotube-linux-${{ env.BUILD_VERSION }}-x86_64.tar.xz
- uses: actions/upload-artifact@v3
if: ${{ inputs.channel == 'nightly' }}
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
dist/Spotube-linux-x86_64.deb
dist/Spotube-linux-x86_64.rpm
dist/spotube-linux-nightly-x86_64.tar.xz
- name: Debug With SSH When fails
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
linux_arm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%Y-%m-%d')"
- name: Install Dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y pkg-config make python3-pip python3-setuptools
- name: Replace pubspec version and BUILD_VERSION Env (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: |
curl -sS https://webi.sh/yq | sh
yq -i '.version |= sub("\+\d+", "+${{ inputs.channel }}.")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV
- name: BUILD_VERSION Env (stable)
if: ${{ inputs.channel == 'stable' }}
run: |
echo "BUILD_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
- name: Create Stable .env
if: ${{ inputs.channel == 'stable' }}
run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
- name: Create Nightly .env
if: ${{ inputs.channel == 'nightly' }}
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- name: Replace Version in files
run: |
sed -i 's|%{{APPDATA_RELEASE}}%|<release version="${{ env.BUILD_VERSION }}" date="${{ steps.date.outputs.date }}" />|' linux/com.github.KRTirtho.Spotube.appdata.xml
- name: Build Binaries (stable)
if: ${{ inputs.channel == 'stable' }}
run: |
docker buildx build --platform=linux/arm64 -f .github/Dockerfile . --build-arg FLUTTER_VERSION=${{env.FLUTTER_VERSION}} --build-arg BUILD_VERSION=${{env.BUILD_VERSION}} -t krtirtho/spotube_linux_arm:latest --load
- name: Build Binaries (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: |
docker buildx build --platform=linux/arm64 -f .github/Dockerfile . --build-arg FLUTTER_VERSION=${{env.FLUTTER_VERSION}} --build-arg BUILD_VERSION=nightly -t krtirtho/spotube_linux_arm:latest --load
- name: Copy the built packages
run: |
docker images ls
docker create --name spotube_linux_arm krtirtho/spotube_linux_arm:latest
docker cp spotube_linux_arm:/app/dist/ dist/
- uses: actions/upload-artifact@v3
if: ${{ inputs.channel == 'stable' }}
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
dist/Spotube-linux-aarch64.deb
dist/spotube-linux-${{ env.BUILD_VERSION }}-aarch64.tar.xz
- uses: actions/upload-artifact@v3
if: ${{ inputs.channel == 'nightly' }}
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
dist/Spotube-linux-aarch64.deb
dist/spotube-linux-nightly-aarch64.tar.xz
- name: Debug With SSH When fails
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
android:
runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: subosito/flutter-action@v2.12.0 - uses: subosito/flutter-action@v2.12.0
@ -299,191 +68,42 @@ jobs:
cache: true cache: true
flutter-version: ${{ env.FLUTTER_VERSION }} flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Setup Java - name: Setup Java
if: ${{matrix.platform == 'android'}}
uses: actions/setup-java@v4 uses: actions/setup-java@v4
with: with:
distribution: 'zulu' distribution: 'zulu'
java-version: '17' java-version: '17'
cache: 'gradle' cache: 'gradle'
check-latest: true check-latest: true
- name: Set up QEMU
if: ${{matrix.platform == 'linux_arm'}}
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: ${{matrix.platform == 'linux_arm'}}
uses: docker/setup-buildx-action@v3
- name: Install Dependencies - name: Install ${{matrix.platform}} dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse xmlstarlet
- name: Replace pubspec version and BUILD_VERSION Env (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: |
curl -sS https://webi.sh/yq | sh
yq -i '.version |= sub("\+\d+", "+${{ inputs.channel }}.")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV
- name: BUILD_VERSION Env (stable)
if: ${{ inputs.channel == 'stable' }}
run: |
echo "BUILD_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
- name: Create Stable .env
if: ${{ inputs.channel == 'stable' }}
run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
- name: Create Nightly .env
if: ${{ inputs.channel == 'nightly' }}
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- name: Generate Secrets
run: | run: |
flutter pub get flutter pub get
dart run build_runner build --delete-conflicting-outputs dart cli/cli.dart install-dependencies --platform=${{matrix.platform}}
- name: Sign Apk - name: Sign Apk
if: ${{matrix.platform == 'android'}}
run: | run: |
echo '${{ secrets.KEYSTORE }}' | base64 --decode > android/app/upload-keystore.jks echo '${{ secrets.KEYSTORE }}' | base64 --decode > android/app/upload-keystore.jks
echo '${{ secrets.KEY_PROPERTIES }}' > android/key.properties echo '${{ secrets.KEY_PROPERTIES }}' > android/key.properties
- name: Build Apk - name: Build ${{matrix.platform}} binaries
run: | run: dart cli/cli.dart build ${{matrix.platform}}
flutter build apk --flavor ${{ inputs.channel }} env:
mv build/app/outputs/flutter-apk/app-${{ inputs.channel }}-release.apk build/Spotube-android-all-arch.apk CHANNEL: ${{inputs.channel}}
DOTENV: ${{secrets.DOTENV_RELEASE}}
- name: Build Playstore AppBundle
run: |
echo 'ENABLE_UPDATE_CHECK=0' >> .env
dart run build_runner build --delete-conflicting-outputs
export MANIFEST=android/app/src/main/AndroidManifest.xml
xmlstarlet ed -d '//meta-data[@android:name="com.google.android.gms.car.application"]' $MANIFEST > $MANIFEST.tmp
mv $MANIFEST.tmp $MANIFEST
flutter build appbundle --flavor ${{ inputs.channel }}
mv build/app/outputs/bundle/${{ inputs.channel }}Release/app-${{ inputs.channel }}-release.aab build/Spotube-playstore-all-arch.aab
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error if-no-files-found: error
name: Spotube-Release-Binaries name: Spotube-Release-Binaries
path: | path: ${{matrix.files}}
build/Spotube-android-all-arch.apk
build/Spotube-playstore-all-arch.aab
- name: Debug With SSH When fails
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
macos:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2.12.0
with:
cache: true
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Replace pubspec version and BUILD_VERSION Env (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: |
brew install yq
yq -i '.version |= sub("\+\d+", "+${{ inputs.channel }}.")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV
- name: BUILD_VERSION Env (stable)
if: ${{ inputs.channel == 'stable' }}
run: |
echo "BUILD_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
- name: Create Stable .env
if: ${{ inputs.channel == 'stable' }}
run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
- name: Create Nightly .env
if: ${{ inputs.channel == 'nightly' }}
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- name: Generate Secrets
run: |
dart pub global activate flutter_distributor
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Build Macos App
run: |
flutter config --enable-macos-desktop
flutter build macos
du -sh build/macos/Build/Products/Release/spotube.app
- name: Package Macos App
run: |
brew install python-setuptools
npm install -g appdmg
mkdir -p build/${{ env.BUILD_VERSION }}
appdmg appdmg.json build/Spotube-macos-universal.dmg
flutter_distributor package --platform=macos --targets pkg --skip-clean
mv dist/**/spotube-*-macos.pkg build/Spotube-macos-universal.pkg
- uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
build/Spotube-macos-universal.dmg
build/Spotube-macos-universal.pkg
- name: Debug With SSH When fails
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
uses: mxschmitt/action-tmate@v3
with:
limit-access-to-actor: true
iOS:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2.10.0
with:
cache: true
flutter-version: ${{ env.FLUTTER_VERSION }}
- name: Replace pubspec version and BUILD_VERSION Env (nightly)
if: ${{ inputs.channel == 'nightly' }}
run: |
brew install yq
yq -i '.version |= sub("\+\d+", "+${{ inputs.channel }}.")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo "BUILD_VERSION=${{ inputs.version }}+${{ inputs.channel }}.${{ github.run_number }}" >> $GITHUB_ENV
- name: BUILD_VERSION Env (stable)
if: ${{ inputs.channel == 'stable' }}
run: |
echo "BUILD_VERSION=${{ inputs.version }}" >> $GITHUB_ENV
- name: Create Stable .env
if: ${{ inputs.channel == 'stable' }}
run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
- name: Create Nightly .env
if: ${{ inputs.channel == 'nightly' }}
run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- name: Generate Secrets
run: |
flutter pub get
dart run build_runner build --delete-conflicting-outputs
- name: Build iOS iPA
run: |
flutter build ios --release --no-codesign --flavor ${{ inputs.channel }}
ln -sf ./build/ios/iphoneos Payload
zip -r9 Spotube-iOS.ipa Payload/${{ inputs.channel }}.app
- uses: actions/upload-artifact@v3
with:
if-no-files-found: error
name: Spotube-Release-Binaries
path: |
Spotube-iOS.ipa
- name: Debug With SSH When fails - name: Debug With SSH When fails
if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }} if: ${{ failure() && inputs.debug && inputs.channel == 'nightly' }}
@ -493,14 +113,8 @@ jobs:
upload: upload:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- windows - build_platform
- linux
- linux_arm
- android
- macos
- iOS
steps: steps:
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
with: with:
@ -517,6 +131,10 @@ jobs:
sha256sum Spotube-Release-Binaries/* >> RELEASE.sha256sum sha256sum Spotube-Release-Binaries/* >> RELEASE.sha256sum
sed -i 's|Spotube-Release-Binaries/||' RELEASE.sha256sum RELEASE.md5sum sed -i 's|Spotube-Release-Binaries/||' RELEASE.sha256sum RELEASE.md5sum
- name: Extract pubspec version
run: |
echo "PUBSPEC_VERSION=$(grep -oP 'version:\s*\K[^+]+(?=\+)' pubspec.yaml)" >> $GITHUB_ENV
- uses: actions/upload-artifact@v3 - uses: actions/upload-artifact@v3
with: with:
if-no-files-found: error if-no-files-found: error
@ -530,7 +148,7 @@ jobs:
uses: ncipollo/release-action@v1 uses: ncipollo/release-action@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
tag: v${{ inputs.version }} # mind the "v" prefix tag: v${{ env.PUBSPEC_VERSION }} # mind the "v" prefix
omitBodyDuringUpdate: true omitBodyDuringUpdate: true
omitNameDuringUpdate: true omitNameDuringUpdate: true
omitPrereleaseDuringUpdate: true omitPrereleaseDuringUpdate: true
@ -548,3 +166,8 @@ jobs:
omitPrereleaseDuringUpdate: true omitPrereleaseDuringUpdate: true
allowUpdates: true allowUpdates: true
artifacts: Spotube-Release-Binaries/*,RELEASE.sha256sum,RELEASE.md5sum artifacts: Spotube-Release-Binaries/*,RELEASE.sha256sum,RELEASE.md5sum
body: |
Build Number: ${{github.run_number}}
Nightly release includes newest features but may contain bugs
It is preferred to use the stable version unless you know what you're doing

View File

@ -1,11 +1,11 @@
# This file tracks properties of this Flutter project. # This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc. # Used by Flutter tool to assess capabilities and perform upgrades etc.
# #
# This file should be version controlled. # This file should be version controlled and should not be manually edited.
version: version:
revision: eb6d86ee27deecba4a83536aa20f366a6044895c revision: "300451adae589accbece3490f4396f10bdf15e6e"
channel: stable channel: "stable"
project_type: app project_type: app
@ -13,11 +13,11 @@ project_type: app
migration: migration:
platforms: platforms:
- platform: root - platform: root
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c create_revision: 300451adae589accbece3490f4396f10bdf15e6e
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c base_revision: 300451adae589accbece3490f4396f10bdf15e6e
- platform: macos - platform: windows
create_revision: eb6d86ee27deecba4a83536aa20f366a6044895c create_revision: 300451adae589accbece3490f4396f10bdf15e6e
base_revision: eb6d86ee27deecba4a83536aa20f366a6044895c base_revision: 300451adae589accbece3490f4396f10bdf15e6e
# User provided section # User provided section

4
cli/README.md Normal file
View File

@ -0,0 +1,4 @@
## Spotube Configuration CLI
This is used for building the project for multiple platforms and having utilities specific for the project.
Written in Dart

16
cli/cli.dart Normal file
View File

@ -0,0 +1,16 @@
import 'package:args/command_runner.dart';
import 'commands/build.dart';
import 'commands/install-dependencies.dart';
void main(List<String> args) {
final commandRunner = CommandRunner(
"cli",
"Configuration CLI for Spotube",
);
commandRunner.addCommand(InstallDependenciesCommand());
commandRunner.addCommand(BuildCommand());
commandRunner.run(args);
}

25
cli/commands/build.dart Normal file
View File

@ -0,0 +1,25 @@
import 'package:args/command_runner.dart';
import 'build/android.dart';
import 'build/ios.dart';
import 'build/linux.dart';
import 'build/linux_arm.dart';
import 'build/macos.dart';
import 'build/windows.dart';
class BuildCommand extends Command {
@override
String get description => "Build for different platforms";
@override
String get name => "build";
BuildCommand() {
addSubcommand(AndroidBuildCommand());
addSubcommand(IosBuildCommand());
addSubcommand(LinuxBuildCommand());
addSubcommand(LinuxArmBuildCommand());
addSubcommand(MacosBuildCommand());
addSubcommand(WindowsBuildCommand());
}
}

View File

@ -0,0 +1,90 @@
import 'dart:async';
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:collection/collection.dart';
import 'package:path/path.dart';
import 'package:xml/xml.dart';
import '../../core/env.dart';
import 'common.dart';
class AndroidBuildCommand extends Command with BuildCommandCommonSteps {
@override
String get description => "Build for android";
@override
String get name => "android";
@override
FutureOr? run() async {
await bootstrap();
await shell.run(
"flutter build apk --flavor ${CliEnv.channel.name}",
);
await dotEnvFile.writeAsString(
"\nENABLE_UPDATE_CHECK=0",
mode: FileMode.append,
);
final androidManifestFile = File(
join(cwd.path, "android", "app", "src", "main", "AndroidManifest.xml"));
final androidManifestXml =
XmlDocument.parse(await androidManifestFile.readAsString());
final deletingElement =
androidManifestXml.findAllElements("meta-data").firstWhereOrNull(
(el) =>
el.getAttribute("android:name") ==
"com.google.android.gms.car.application",
);
deletingElement?.parent?.children.remove(deletingElement);
await androidManifestFile.writeAsString(
androidManifestXml.toXmlString(pretty: true),
);
await shell.run(
"""
dart run build_runner build --delete-conflicting-outputs
flutter build appbundle --flavor ${CliEnv.channel.name}
""",
);
final ogApkFile = File(
join(
"build",
"app",
"outputs",
"flutter-apk",
"app-${CliEnv.channel.name}-release.apk",
),
);
await ogApkFile.copy(
join(cwd.path, "build", "Spotube-android-all-arch.apk"),
);
final ogAppbundleFile = File(
join(
cwd.path,
"build",
"app",
"outputs",
"bundle",
"${CliEnv.channel.name}Release",
"app-${CliEnv.channel.name}-release.aab",
),
);
await ogAppbundleFile.copy(
join(cwd.path, "build", "Spotube-playstore-all-arch.aab"),
);
stdout.writeln("✅ Built Android Apk and Appbundle");
}
}

View File

@ -0,0 +1,66 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:path/path.dart';
import 'package:process_run/shell_run.dart';
import 'package:pubspec_parse/pubspec_parse.dart';
import '../../core/env.dart';
mixin BuildCommandCommonSteps on Command {
final shell = Shell();
Directory get cwd => Directory.current;
Pubspec? _pubspec;
Pubspec get pubspec {
if (_pubspec != null) {
return _pubspec!;
}
final pubspecFile = File(join(cwd.path, "pubspec.yaml"));
_pubspec = Pubspec.parse(pubspecFile.readAsStringSync());
return _pubspec!;
}
String get versionWithoutBuildNumber {
return "${pubspec.version!.major}.${pubspec.version!.minor}.${pubspec.version!.patch}";
}
RegExp get versionVarRegExp =>
RegExp(r"\%\{\{SPOTUBE_VERSION\}\}\%", multiLine: true);
File get dotEnvFile => File(join(cwd.path, ".env"));
Future<void> bootstrap() async {
await dotEnvFile.create(recursive: true);
await dotEnvFile.writeAsString(
"${CliEnv.dotenv}\n"
"RELEASE_CHANNEL=${CliEnv.channel.name}\n",
);
if (CliEnv.channel == BuildChannel.nightly) {
final pubspecFile = File(join(cwd.path, "pubspec.yaml"));
pubspecFile.writeAsStringSync(
pubspecFile.readAsStringSync().replaceAll(
"version: ${pubspec.version!.canonicalizedVersion}",
"version: $versionWithoutBuildNumber+${CliEnv.ghRunNumber}",
),
);
_pubspec = null;
pubspec;
}
await shell.run(
"""
flutter pub get
dart run build_runner build --delete-conflicting-outputs
dart pub global activate flutter_distributor
""",
);
}
}

View File

@ -0,0 +1,29 @@
import 'dart:async';
import 'package:args/command_runner.dart';
import 'package:path/path.dart';
import '../../core/env.dart';
import 'common.dart';
class IosBuildCommand extends Command with BuildCommandCommonSteps {
@override
String get description => "iOS build command";
@override
String get name => "ios";
@override
FutureOr? run() async {
await bootstrap();
final buildDirPath = join(cwd.path, "build", "ios", "iphoneos");
await shell.run(
"""
flutter build ios --release --no-codesign --flavor ${CliEnv.channel.name}
ln -sf $buildDirPath Payload
zip -r9 Spotube-iOS.ipa ${join("Payload", "${CliEnv.channel.name}.app")}
""",
);
}
}

View File

@ -0,0 +1,106 @@
import 'dart:async';
import 'dart:io';
import 'package:io/io.dart';
import 'package:args/command_runner.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart';
import '../../core/env.dart';
import 'common.dart';
class LinuxBuildCommand extends Command with BuildCommandCommonSteps {
@override
String get description => "Linux build command";
@override
String get name => "linux";
@override
FutureOr? run() async {
stdout.writeln("Replacing versions");
final appDataFile = File(
join(cwd.path, "linux", "com.github.KRTirtho.Spotube.appdata.xml"),
);
appDataFile.writeAsStringSync(
appDataFile.readAsStringSync().replaceAll(
versionVarRegExp,
'<release'
' version="$versionWithoutBuildNumber"'
' date="${DateFormat("yyyy-MM-dd").format(DateTime.now())}"'
'/>',
),
);
await bootstrap();
await shell.run(
"""
flutter_distributor package --platform=linux --targets=deb
flutter_distributor package --platform=linux --targets=rpm
""",
);
final tempDir = join(Directory.systemTemp.path, "spotube-tar");
final bundleDirPath =
join(cwd.path, "build", "linux", "x64", "release", "bundle");
final tarFile = File(join(
cwd.path,
"dist",
"spotube-linux-"
"${CliEnv.channel == BuildChannel.nightly ? "nightly" : versionWithoutBuildNumber}"
"-x86_64.tar.xz",
));
await copyPath(bundleDirPath, tempDir);
await File(join(cwd.path, "linux", "spotube.desktop")).copy(
join(tempDir, "spotube.desktop"),
);
await File(
join(cwd.path, "linux", "com.github.KRTirtho.Spotube.appdata.xml"),
).copy(
join(tempDir, "com.github.KRTirtho.Spotube.appdata.xml"),
);
await File(join(cwd.path, "assets", "spotube-logo.png")).copy(
join(tempDir, "spotube-logo.png"),
);
await shell.run(
"tar -cJf ${tarFile.path} -C $tempDir .",
);
final ogDeb = File(
join(
cwd.path,
"dist",
pubspec.version.toString(),
"spotube-${pubspec.version}-linux.deb",
),
);
final ogRpm = File(
join(
cwd.path,
"dist",
pubspec.version.toString(),
"spotube-${pubspec.version}-linux.rpm",
),
);
await ogDeb.copy(
join(cwd.path, "dist", "Spotube-linux-x86_64.deb"),
);
await ogRpm.copy(
join(cwd.path, "dist", "Spotube-linux-x86_64.rpm"),
);
await ogDeb.delete();
await ogRpm.delete();
stdout.writeln("✅ Linux building done");
}
}

View File

@ -0,0 +1,37 @@
import 'dart:async';
import 'package:args/command_runner.dart';
import 'package:path/path.dart';
import '../../core/env.dart';
import 'common.dart';
class LinuxArmBuildCommand extends Command with BuildCommandCommonSteps {
@override
String get description => "Build Linux Arm";
@override
String get name => "linux_arm";
@override
FutureOr? run() async {
await bootstrap();
await shell.run(
"docker buildx build --platform=linux/arm64 "
"-f ${join(cwd.path, ".github", "Dockerfile")} ${cwd.path} "
"--build-arg FLUTTER_VERSION=${CliEnv.flutterVersion} "
"--build-arg BUILD_VERSION=${CliEnv.channel == BuildChannel.nightly ? "nightly" : versionWithoutBuildNumber} "
"-t krtirtho/spotube_linux_arm:latest "
"--load",
);
await shell.run(
"""
docker images ls
docker create --name spotube_linux_arm krtirtho/spotube_linux_arm:latest
docker cp spotube_linux_arm:/app/dist/ dist/
""",
);
}
}

View File

@ -0,0 +1,42 @@
import 'dart:async';
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:path/path.dart';
import 'common.dart';
class MacosBuildCommand extends Command with BuildCommandCommonSteps {
@override
String get description => "Macos Build command";
@override
String get name => "macos";
@override
FutureOr? run() async {
await bootstrap();
await shell.run(
"""
flutter build macos
appdmg appdmg.json ${join(cwd.path, "build", "Spotube-macos-universal.dmg")}
flutter_distributor package --platform=macos --targets pkg --skip-clean
""",
);
final ogPkg = File(
join(
cwd.path,
"dist",
pubspec.version.toString(),
"spotube-${pubspec.version}-macos.pkg",
),
);
await ogPkg.copy(
join(cwd.path, "build", "Spotube-macos-universal.pkg"),
);
await ogPkg.delete();
}
}

View File

@ -0,0 +1,100 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:path/path.dart';
import 'package:crypto/crypto.dart';
import 'common.dart';
class WindowsBuildCommand extends Command with BuildCommandCommonSteps {
@override
String get description => "Build Windows exe";
@override
String get name => "windows";
Future<void> innoDependInstall() async {
final innoDependencyPath = join(cwd.path, "build", "inno-depend");
await shell.run(
"git clone https://github.com/DomGries/InnoDependencyInstaller.git $innoDependencyPath",
);
}
@override
void run() async {
stdout.writeln("Replace versions");
final chocoFiles = [
join(cwd.path, "choco-struct", "tools", "VERIFICATION.txt"),
join(cwd.path, "choco-struct", "spotube.nuspec"),
];
for (final filePath in chocoFiles) {
final file = File(filePath);
final content = file.readAsStringSync();
final newContent =
content.replaceAll(versionVarRegExp, versionWithoutBuildNumber);
file.writeAsStringSync(newContent);
}
await bootstrap();
await innoDependInstall();
await shell.run(
"flutter_distributor package --platform=windows --targets=exe --skip-clean",
);
final ogExe = File(
join(
cwd.path,
"dist",
pubspec.version.toString(),
"spotube-${pubspec.version}-windows-setup.exe",
),
);
final exePath = join(cwd.path, "dist", "Spotube-windows-x86_64-setup.exe");
await ogExe.copy(exePath);
await ogExe.delete();
stdout.writeln("✅ Windows exe built at $exePath");
final exeFile = File(exePath);
final hash = sha256.convert(await exeFile.readAsBytes()).toString();
final chocoVerificationFile = File(chocoFiles.first);
chocoVerificationFile.writeAsStringSync(
chocoVerificationFile.readAsStringSync().replaceAll(
RegExp(r"\%\{\{WIN_SHA256\}\}\%"),
hash,
),
);
await exeFile.copy(
join(cwd.path, "choco-struct", "tools", basename(exeFile.path)),
);
await shell.run(
"choco pack ${chocoFiles[1]} --outputdirectory ${join(cwd.path, "dist")}",
);
final chocoNupkg = File(
join(cwd.path, "dist", "spotube.$versionWithoutBuildNumber.nupkg"),
);
final distNupkgPath = join(
cwd.path,
"dist",
"Spotube-windows-x86_64.nupkg",
);
await chocoNupkg.copy(distNupkgPath);
await chocoNupkg.delete();
stdout.writeln("✅ Windows nupkg built at $distNupkgPath");
}
}

View File

@ -0,0 +1,74 @@
import 'dart:async';
import 'package:args/command_runner.dart';
import 'package:process_run/shell_run.dart';
class InstallDependenciesCommand extends Command {
@override
String get description => "Install platform dependencies";
@override
String get name => "install-dependencies";
InstallDependenciesCommand() {
argParser.addOption(
"platform",
abbr: "p",
allowed: [
"windows",
"linux",
"linux_arm",
"macos",
"ios",
"android",
],
mandatory: true,
);
}
@override
FutureOr? run() async {
final shell = Shell();
switch (argResults!.option("platform")) {
case "windows":
break;
case "linux":
await shell.run(
"""
sudo apt-get update -y
sudo apt-get install -y tar clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse libunwind-dev locate patchelf gir1.2-appindicator3-0.1 libappindicator3-1 libappindicator3-dev libsecret-1-0 libjsoncpp25 libsecret-1-dev libjsoncpp-dev libnotify-bin libnotify-dev mpv libmpv-dev
""",
);
break;
case "linux_arm":
await shell.run(
"""
sudo apt-get update -y
sudo apt-get install -y pkg-config make python3-pip python3-setuptools
""",
);
break;
case "macos":
await shell.run(
"""
brew install python-setuptools
npm install -g appdmg
""",
);
break;
case "ios":
break;
case "android":
await shell.run(
"""
sudo apt-get update -y
sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse
""",
);
break;
default:
break;
}
}
}

24
cli/core/env.dart Normal file
View File

@ -0,0 +1,24 @@
import 'dart:io';
enum BuildChannel {
stable,
nightly;
factory BuildChannel.fromEnvironment(String name) {
final channel = Platform.environment[name]!;
if (channel == "stable") {
return BuildChannel.stable;
} else if (channel == "nightly") {
return BuildChannel.nightly;
} else {
throw Exception("Invalid channel: $channel");
}
}
}
class CliEnv {
static final channel = BuildChannel.fromEnvironment("CHANNEL");
static final dotenv = Platform.environment["DOTENV"]!;
static final ghRunNumber = Platform.environment["GITHUB_RUN_NUMBER"];
static final flutterVersion = Platform.environment["FLUTTER_VERSION"]!;
}

View File

@ -3,6 +3,11 @@ import 'package:spotube/utils/platform.dart';
part 'env.g.dart'; part 'env.g.dart';
enum ReleaseChannel {
nightly,
stable,
}
@Envied(obfuscate: true, requireEnvFile: true, path: ".env") @Envied(obfuscate: true, requireEnvFile: true, path: ".env")
abstract class Env { abstract class Env {
@EnviedField(varName: 'SPOTIFY_SECRETS') @EnviedField(varName: 'SPOTIFY_SECRETS')
@ -25,6 +30,13 @@ abstract class Env {
@EnviedField(varName: 'ENABLE_UPDATE_CHECK', defaultValue: "1") @EnviedField(varName: 'ENABLE_UPDATE_CHECK', defaultValue: "1")
static final String _enableUpdateChecker = _Env._enableUpdateChecker; static final String _enableUpdateChecker = _Env._enableUpdateChecker;
@EnviedField(varName: "RELEASE_CHANNEL", defaultValue: "nightly")
static final String _releaseChannel = _Env._releaseChannel;
static ReleaseChannel get releaseChannel => _releaseChannel == "stable"
? ReleaseChannel.stable
: ReleaseChannel.nightly;
static bool get enableUpdateChecker => static bool get enableUpdateChecker =>
kIsFlatpak || _enableUpdateChecker == "1"; kIsFlatpak || _enableUpdateChecker == "1";

View File

@ -5,18 +5,23 @@ import 'package:version/version.dart';
class RootAppUpdateDialog extends StatelessWidget { class RootAppUpdateDialog extends StatelessWidget {
final Version? version; final Version? version;
const RootAppUpdateDialog({super.key, this.version}); final int? nightlyBuildNum;
const RootAppUpdateDialog({super.key, this.version}) : nightlyBuildNum = null;
const RootAppUpdateDialog.nightly({super.key, required this.nightlyBuildNum})
: version = null;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
const url = "https://spotube.krtirtho.dev/downloads"; const url = "https://spotube.krtirtho.dev/downloads";
const nightlyUrl = "https://spotube.krtirtho.dev/downloads/nightly";
return AlertDialog( return AlertDialog(
title: const Text("Spotube has an update"), title: const Text("Spotube has an update"),
actions: [ actions: [
FilledButton( FilledButton(
child: const Text("Download Now"), child: const Text("Download Now"),
onPressed: () => launchUrlString( onPressed: () => launchUrlString(
url, nightlyBuildNum != null ? nightlyUrl : url,
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
), ),
), ),
@ -24,21 +29,26 @@ class RootAppUpdateDialog extends StatelessWidget {
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text("Spotube v$version has been released"), Text(
Row( nightlyBuildNum != null
mainAxisAlignment: MainAxisAlignment.center, ? "Spotube Nightly $nightlyBuildNum has been released"
children: [ : "Spotube v$version has been released",
const Text("Read the latest "),
AnchorButton(
"release notes",
style: const TextStyle(color: Colors.blue),
onTap: () => launchUrlString(
url,
mode: LaunchMode.externalApplication,
),
),
],
), ),
if (nightlyBuildNum == null)
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text("Read the latest "),
AnchorButton(
"release notes",
style: const TextStyle(color: Colors.blue),
onTap: () => launchUrlString(
url,
mode: LaunchMode.externalApplication,
),
),
],
),
], ],
), ),
); );

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:spotube/collections/assets.gen.dart'; import 'package:spotube/collections/assets.gen.dart';
import 'package:spotube/collections/env.dart';
import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/components/shared/links/hyper_link.dart'; import 'package:spotube/components/shared/links/hyper_link.dart';
import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart';
@ -72,6 +73,13 @@ class AboutSpotube extends HookConsumerWidget {
Text("v${packageInfo.version}") Text("v${packageInfo.version}")
], ],
), ),
TableRow(
children: [
Text(context.l10n.channel),
colon,
Text(Env.releaseChannel.name)
],
),
TableRow( TableRow(
children: [ children: [
Text(context.l10n.build_number), Text(context.l10n.build_number),

View File

@ -335,35 +335,59 @@ abstract class ServiceUtils {
) async { ) async {
if (!Env.enableUpdateChecker) return; if (!Env.enableUpdateChecker) return;
if (!ref.read(userPreferencesProvider.select((s) => s.checkUpdate))) return; if (!ref.read(userPreferencesProvider.select((s) => s.checkUpdate))) return;
final packageInfo = await PackageInfo.fromPlatform(); final packageInfo = await PackageInfo.fromPlatform();
final value = await http.get( if (Env.releaseChannel == ReleaseChannel.nightly) {
Uri.parse( final value = await http.get(
"https://api.github.com/repos/KRTirtho/spotube/releases/latest", Uri.parse(
), "https://api.github.com/repos/KRTirtho/spotube/actions/workflows/spotube-release-binary.yml/runs?status=success&per_page=1",
); ),
final tagName = );
(jsonDecode(value.body)["tag_name"] as String).replaceAll("v", "");
final currentVersion = packageInfo.version == "Unknown"
? null
: Version.parse(packageInfo.version);
final latestVersion = tagName == "nightly" ? null : Version.parse(tagName);
if (currentVersion == null || final buildNum =
latestVersion == null || jsonDecode(value.body)["workflow_runs"][0]["run_number"] as int;
(latestVersion.isPreRelease && !currentVersion.isPreRelease) ||
(!latestVersion.isPreRelease && currentVersion.isPreRelease)) return;
if (latestVersion <= currentVersion || !context.mounted) return; if (buildNum <= int.parse(packageInfo.buildNumber) || !context.mounted) {
return;
}
showDialog( await showDialog(
context: context, context: context,
barrierDismissible: true, barrierDismissible: true,
barrierColor: Colors.black26, barrierColor: Colors.black26,
builder: (context) { builder: (context) {
return RootAppUpdateDialog(version: latestVersion); return RootAppUpdateDialog.nightly(nightlyBuildNum: buildNum);
}, },
); );
} else {
final value = await http.get(
Uri.parse(
"https://api.github.com/repos/KRTirtho/spotube/releases/latest",
),
);
final tagName =
(jsonDecode(value.body)["tag_name"] as String).replaceAll("v", "");
final currentVersion = packageInfo.version == "Unknown"
? null
: Version.parse(packageInfo.version);
final latestVersion =
tagName == "nightly" ? null : Version.parse(tagName);
if (currentVersion == null ||
latestVersion == null ||
(latestVersion.isPreRelease && !currentVersion.isPreRelease) ||
(!latestVersion.isPreRelease && currentVersion.isPreRelease)) return;
if (latestVersion <= currentVersion || !context.mounted) return;
showDialog(
context: context,
barrierDismissible: true,
barrierColor: Colors.black26,
builder: (context) {
return RootAppUpdateDialog(version: latestVersion);
},
);
}
} }
} }

View File

@ -45,10 +45,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: archive name: archive
sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" sha256: ecf4273855368121b1caed0d10d4513c7241dfc813f7d3c8933b36622ae9b265
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.4.10" version: "3.5.1"
args: args:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1271,7 +1271,7 @@ packages:
source: hosted source: hosted
version: "3.1.14" version: "3.1.14"
io: io:
dependency: transitive dependency: "direct dev"
description: description:
name: io name: io
sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e"
@ -1702,14 +1702,6 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.8" version: "2.1.8"
pointycastle:
dependency: transitive
description:
name: pointycastle
sha256: "70fe966348fe08c34bf929582f1d8247d9d9408130723206472b4687227e4333"
url: "https://pub.dev"
source: hosted
version: "3.8.0"
pool: pool:
dependency: transitive dependency: transitive
description: description:
@ -1734,6 +1726,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.2" version: "5.0.2"
process_run:
dependency: "direct dev"
description:
name: process_run
sha256: "8d9c6198b98fbbfb511edd42e7364e24d85c163e47398919871b952dc86a423e"
url: "https://pub.dev"
source: hosted
version: "0.14.2"
provider: provider:
dependency: transitive dependency: transitive
description: description:
@ -2462,7 +2462,7 @@ packages:
source: hosted source: hosted
version: "1.0.4" version: "1.0.4"
xml: xml:
dependency: transitive dependency: "direct dev"
description: description:
name: xml name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226

View File

@ -144,6 +144,9 @@ dev_dependencies:
freezed: ^2.5.2 freezed: ^2.5.2
custom_lint: ^0.6.4 custom_lint: ^0.6.4
riverpod_lint: ^2.3.10 riverpod_lint: ^2.3.10
process_run: ^0.14.2
xml: ^6.5.0
io: ^1.0.4
dependency_overrides: dependency_overrides:
uuid: ^4.4.0 uuid: ^4.4.0

View File

@ -1,13 +1,16 @@
# Project-level configuration.
cmake_minimum_required(VERSION 3.14) cmake_minimum_required(VERSION 3.14)
project(spotube LANGUAGES CXX) project(spotube LANGUAGES CXX)
# The name of the executable created for the application. Change this to change
# the on-disk name of your application.
set(BINARY_NAME "spotube") set(BINARY_NAME "spotube")
cmake_policy(SET CMP0063 NEW) # Explicitly opt in to modern CMake behaviors to avoid warnings with recent
# versions of CMake.
cmake_policy(VERSION 3.14...3.25)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") # Define build configuration option.
# Configure build options.
get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(IS_MULTICONFIG) if(IS_MULTICONFIG)
set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release"
@ -20,7 +23,7 @@ else()
"Debug" "Profile" "Release") "Debug" "Profile" "Release")
endif() endif()
endif() endif()
# Define settings for the Profile build mode.
set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}")
set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}")
@ -30,6 +33,10 @@ set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}")
add_definitions(-DUNICODE -D_UNICODE) add_definitions(-DUNICODE -D_UNICODE)
# Compilation settings that should be applied to most targets. # Compilation settings that should be applied to most targets.
#
# Be cautious about adding new options here, as plugins use this function by
# default. In most cases, you should add new options to specific targets instead
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET) function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_17) target_compile_features(${TARGET} PUBLIC cxx_std_17)
target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100")
@ -38,14 +45,14 @@ function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>") target_compile_definitions(${TARGET} PRIVATE "$<$<CONFIG:Debug>:_DEBUG>")
endfunction() endfunction()
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
# Flutter library and tool build rules. # Flutter library and tool build rules.
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
add_subdirectory(${FLUTTER_MANAGED_DIR}) add_subdirectory(${FLUTTER_MANAGED_DIR})
# Application build # Application build; see runner/CMakeLists.txt.
add_subdirectory("runner") add_subdirectory("runner")
# Generated plugin build rules, which manage building the plugins and adding # Generated plugin build rules, which manage building the plugins and adding
# them to the application. # them to the application.
include(flutter/generated_plugins.cmake) include(flutter/generated_plugins.cmake)
@ -80,6 +87,12 @@ if(PLUGIN_BUNDLED_LIBRARIES)
COMPONENT Runtime) COMPONENT Runtime)
endif() endif()
# Copy the native assets provided by the build.dart from all packages.
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/")
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
COMPONENT Runtime)
# Fully re-copy the assets directory on each build to avoid having stale files # Fully re-copy the assets directory on each build to avoid having stale files
# from a previous install. # from a previous install.
set(FLUTTER_ASSET_DIR_NAME "flutter_assets") set(FLUTTER_ASSET_DIR_NAME "flutter_assets")

View File

@ -60,16 +60,16 @@ IDI_APP_ICON ICON "resources\\app_icon.ico"
// Version // Version
// //
#ifdef FLUTTER_BUILD_NUMBER #if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD)
#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER #define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD
#else #else
#define VERSION_AS_NUMBER 1,0,0 #define VERSION_AS_NUMBER 1,0,0,0
#endif #endif
#ifdef FLUTTER_BUILD_NAME #if defined(FLUTTER_VERSION)
#define VERSION_AS_STRING #FLUTTER_BUILD_NAME #define VERSION_AS_STRING FLUTTER_VERSION
#else #else
#define VERSION_AS_STRING "%{{SPOTUBE_VERSION}}%" #define VERSION_AS_STRING "3.6.0"
#endif #endif
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
@ -93,7 +93,7 @@ BEGIN
VALUE "FileDescription", "Spotube" "\0" VALUE "FileDescription", "Spotube" "\0"
VALUE "FileVersion", VERSION_AS_STRING "\0" VALUE "FileVersion", VERSION_AS_STRING "\0"
VALUE "InternalName", "spotube" "\0" VALUE "InternalName", "spotube" "\0"
VALUE "LegalCopyright", "Copyright (C) 2022 oss.krtirtho. All rights reserved." "\0" VALUE "LegalCopyright", "Copyright (C) 2024 oss.krtirtho. All rights reserved." "\0"
VALUE "OriginalFilename", "spotube.exe" "\0" VALUE "OriginalFilename", "spotube.exe" "\0"
VALUE "ProductName", "spotube" "\0" VALUE "ProductName", "spotube" "\0"
VALUE "ProductVersion", VERSION_AS_STRING "\0" VALUE "ProductVersion", VERSION_AS_STRING "\0"