name: Release Draft on: workflow_dispatch: env: FLUTTER_VERSION: "3.41.9" RUST_VERSION: "1.84.1" APK_BUILD_DIR: "/tmp/build" jobs: build: runs-on: ubuntu-24.04 outputs: version: ${{ steps.get_version.outputs.version }} steps: - uses: actions/checkout@v6 - name: Get version from pubspec.yaml id: get_version run: | VERSION=$(sed -n 's/^version: \([0-9]*\.[0-9]*\.[0-9]*\).*/\1/p' app/pubspec.yaml) echo "version=$VERSION" >> $GITHUB_OUTPUT build_apk: needs: build runs-on: ubuntu-22.04 steps: - name: Checkout repository uses: actions/checkout@v6 - name: Remove proprietary dependencies run: sh scripts/remove_proprietary_dependencies.sh - name: Copy files to env.APK_BUILD_DIR run: | mkdir -p $APK_BUILD_DIR cp -r . $APK_BUILD_DIR - name: Decode key.properties file working-directory: ${{ env.APK_BUILD_DIR }} env: ENCODED_STRING: ${{ secrets.ANDROID_KEY_PROPERTIES }} run: echo $ENCODED_STRING | base64 -di > app/android/key.properties - name: Decode android-keystore.jks file working-directory: ${{ env.APK_BUILD_DIR }} env: ENCODED_STRING: ${{ secrets.ANDROID_KEY_STORE }} run: mkdir secrets && echo $ENCODED_STRING | base64 -di > secrets/android-keystore.jks - name: Set up JDK 17 uses: actions/setup-java@v5 with: distribution: 'temurin' java-version: '17' - name: Install Flutter uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: stable override: ${{ env.RUST_VERSION }} - name: Check rust-toolchain.toml working-directory: ${{ env.APK_BUILD_DIR }}/app run: rustup show - name: Dependencies working-directory: ${{ env.APK_BUILD_DIR }}/app run: flutter pub get - name: Build APK working-directory: ${{ env.APK_BUILD_DIR }}/app run: flutter build apk --split-per-abi - name: Upload APK uses: actions/upload-artifact@v6 with: name: apk-result path: | ${{ env.APK_BUILD_DIR }}/app/build/app/outputs/flutter-apk/app-armeabi-v7a-release.apk ${{ env.APK_BUILD_DIR }}/app/build/app/outputs/flutter-apk/app-arm64-v8a-release.apk ${{ env.APK_BUILD_DIR }}/app/build/app/outputs/flutter-apk/app-x86_64-release.apk build_tar_x86_64: needs: build runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y clang cmake libgtk-3-dev ninja-build libayatana-appindicator3-dev - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} channel: "stable" - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: stable override: ${{ env.RUST_VERSION }} - name: Check rust-toolchain.toml working-directory: app run: rustup show - name: Dependencies working-directory: app run: flutter pub get - name: Compile linux working-directory: app run: flutter build linux - name: Create tar.gz archive run: | cd app/build/linux/x64/release/bundle tar -czvf ../../../../../result.tar.gz * - name: Upload tar.gz archive uses: actions/upload-artifact@v6 with: name: tar-gz-x86-64-result path: ./app/*.tar.gz # Manage the Flutter version on the self-hosted runner manually! # Flutter currently doesn't provide Linux ARM64 binaries. build_tar_arm_64: needs: build runs-on: [ self-hosted, linux, arm64 ] steps: - uses: actions/checkout@v6 - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y clang cmake libgtk-3-dev ninja-build libayatana-appindicator3-dev - name: Dependencies working-directory: app run: flutter pub get - name: Compile linux working-directory: app run: flutter build linux - name: Create tar.gz archive run: | cd app/build/linux/arm64/release/bundle tar -czvf ../../../../../result.tar.gz * - name: Upload tar.gz archive uses: actions/upload-artifact@v6 with: name: tar-gz-arm-64-result path: ./app/*.tar.gz build_deb_x86_64: needs: build runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y clang cmake libgtk-3-dev ninja-build libayatana-appindicator3-dev - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} channel: "stable" - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: stable override: ${{ env.RUST_VERSION }} - name: Check rust-toolchain.toml working-directory: app run: rustup show - name: Enable dart_distributor run: dart pub global activate flutter_distributor - name: Update PATH run: echo 'export PATH="$PATH:$HOME/.pub-cache/bin"' >> ~/.bashrc - name: Build deb package working-directory: app run: flutter_distributor package --platform linux --targets deb - name: Find deb file id: find_deb run: | VERSION=${{ needs.build.outputs.version }} DEB_PATH=$(find app/dist -name "localsend_app-$VERSION*-linux.deb") echo "deb_path=$DEB_PATH" >> $GITHUB_OUTPUT - name: Check if deb file exists id: check_file run: | if [[ ! -f "${{ steps.find_deb.outputs.deb_path }}" ]]; then echo "File not found: ${{ steps.find_deb.outputs.deb_path }}" exit 1 fi - name: Upload deb file uses: actions/upload-artifact@v6 with: name: deb-x86-64-result path: ${{ steps.find_deb.outputs.deb_path }} # Manage the Flutter version on the self-hosted runner manually! # Flutter currently doesn't provide Linux ARM64 binaries. build_deb_arm_64: needs: build runs-on: [ self-hosted, linux, arm64 ] steps: - uses: actions/checkout@v6 - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y clang cmake libgtk-3-dev ninja-build libayatana-appindicator3-dev - name: Enable dart_distributor run: dart pub global activate flutter_distributor - name: Build deb package working-directory: app run: PATH="$PATH:$HOME/.pub-cache/bin" flutter_distributor package --platform linux --targets deb - name: Find deb file id: find_deb run: | VERSION=${{ needs.build.outputs.version }} DEB_PATH=$(find app/dist -name "localsend_app-$VERSION*-linux.deb") echo "deb_path=$DEB_PATH" >> $GITHUB_OUTPUT - name: Check if deb file exists id: check_file run: | if [[ ! -f "${{ steps.find_deb.outputs.deb_path }}" ]]; then echo "File not found: ${{ steps.find_deb.outputs.deb_path }}" exit 1 fi - name: Upload deb file uses: actions/upload-artifact@v6 with: name: deb-arm-64-result path: ${{ steps.find_deb.outputs.deb_path }} build_appimage_x86_64: needs: build runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - name: Install dependencies run: | sudo apt-get update sudo apt-get install -y clang cmake libgtk-3-dev ninja-build libayatana-appindicator3-dev libfuse2 - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} channel: "stable" - name: Install Rust uses: actions-rs/toolchain@v1 with: toolchain: stable override: ${{ env.RUST_VERSION }} - name: Check rust-toolchain.toml working-directory: app run: rustup show - name: Dependencies working-directory: app run: flutter pub get - name: Compile linux working-directory: app run: flutter build linux - name: Copy compiled linux files run: | mkdir AppDir cp -r app/build/linux/x64/release/bundle/* AppDir/ - name: Copy logo to AppDir run: | mkdir -p AppDir/usr/share/icons/hicolor/32x32/apps cp app/assets/img/logo-32.png AppDir/usr/share/icons/hicolor/32x32/apps/localsend.png mkdir -p AppDir/usr/share/icons/hicolor/128x128/apps cp app/assets/img/logo-128.png AppDir/usr/share/icons/hicolor/128x128/apps/localsend.png mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps cp app/assets/img/logo-256.png AppDir/usr/share/icons/hicolor/256x256/apps/localsend.png - name: Copy Recipe to correct location run: cp scripts/appimage/AppImageBuilder_x86_64.yml AppImageBuilder.yml - name: Build AppImage uses: AppImageCrafters/build-appimage@57c3bc6963f870ce3be103117de5b5e33ffbaeb6 with: recipe: ./AppImageBuilder.yml - name: Upload AppImage file uses: actions/upload-artifact@v6 with: name: appimage-x86-64-result path: ./*.AppImage build_windows_zip_x86_64: needs: build runs-on: windows-latest steps: - name: Fix long file paths run: git config --system core.longpaths true - name: Checkout repository uses: actions/checkout@v6 - uses: subosito/flutter-action@v2 with: flutter-version: ${{ env.FLUTTER_VERSION }} channel: "stable" - name: Dependencies working-directory: app run: flutter pub get - name: Compile for Windows working-directory: app run: flutter build windows - name: Create empty settings.json working-directory: app run: echo {} > build/windows/x64/runner/Release/settings.json - name: Add DLL files working-directory: app run: | Copy-Item ../scripts/windows/x64/msvcp140.dll build/windows/x64/runner/Release/ Copy-Item ../scripts/windows/x64/vcruntime140.dll build/windows/x64/runner/Release/ Copy-Item ../scripts/windows/x64/vcruntime140_1.dll build/windows/x64/runner/Release/ - name: Zip compiled files working-directory: app run: Compress-Archive -Path build/windows/x64/runner/Release/* -DestinationPath LocalSend.zip - name: Upload zip uses: actions/upload-artifact@v6 with: name: windows-zip-x86-64-result path: app/LocalSend.zip release: needs: - build - build_apk - build_tar_x86_64 - build_tar_arm_64 - build_deb_x86_64 - build_deb_arm_64 - build_appimage_x86_64 - build_windows_zip_x86_64 runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - name: Draft release id: draft_release uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag: v${{ needs.build.outputs.version }} name: v${{ needs.build.outputs.version }} # APK - name: Download apk file uses: actions/download-artifact@v7 with: name: apk-result path: apk-result - name: Copy apk file to root run: cp apk-result/*.apk . - name: Upload Release Asset (arm32v7) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: app-armeabi-v7a-release.apk asset_name: LocalSend-${{ needs.build.outputs.version }}-android-arm32v7.apk asset_content_type: application/vnd.android.package-archive - name: Upload Release Asset (arm64v8) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: app-arm64-v8a-release.apk asset_name: LocalSend-${{ needs.build.outputs.version }}-android-arm64v8.apk asset_content_type: application/vnd.android.package-archive - name: Upload Release Asset (x64) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: app-x86_64-release.apk asset_name: LocalSend-${{ needs.build.outputs.version }}-android-x64.apk asset_content_type: application/vnd.android.package-archive # TAR.GZ (x86_64) - name: Download tar.gz file uses: actions/download-artifact@v7 with: name: tar-gz-x86-64-result path: tar-gz-x86-64-result - name: List files in tar.gz-directory run: ls -l tar-gz-x86-64-result - name: Copy tar.gz file to root run: cp tar-gz-x86-64-result/* result.tar.gz - name: Upload Release Asset (tar.gz) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: result.tar.gz asset_name: LocalSend-${{ needs.build.outputs.version }}-linux-x86-64.tar.gz asset_content_type: application/gzip # TAR.GZ (arm_64) - name: Download tar.gz file uses: actions/download-artifact@v7 with: name: tar-gz-arm-64-result path: tar-gz-arm-64-result - name: List files in tar.gz-directory run: ls -l tar-gz-arm-64-result - name: Copy tar.gz file to root run: cp tar-gz-arm-64-result/* result.tar.gz - name: Upload Release Asset (tar.gz) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: result.tar.gz asset_name: LocalSend-${{ needs.build.outputs.version }}-linux-arm-64.tar.gz asset_content_type: application/gzip # DEB (x86_64) - name: Download deb file uses: actions/download-artifact@v7 with: name: deb-x86-64-result path: deb-x86-64-result - name: Copy deb file to root run: cp deb-x86-64-result/*.deb result.deb - name: Upload Release Asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: result.deb asset_name: LocalSend-${{ needs.build.outputs.version }}-linux-x86-64.deb asset_content_type: application/vnd.debian.binary-package # DEB (arm_64) - name: Download deb file uses: actions/download-artifact@v7 with: name: deb-arm-64-result path: deb-arm-64-result - name: Copy deb file to root run: cp deb-arm-64-result/*.deb result.deb - name: Upload Release Asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: result.deb asset_name: LocalSend-${{ needs.build.outputs.version }}-linux-arm-64.deb asset_content_type: application/vnd.debian.binary-package # APPIMAGE (x86_64) - name: Download AppImage file uses: actions/download-artifact@v7 with: name: appimage-x86-64-result path: appimage-x86-64-result - name: List files in appimage-directory run: ls -l appimage-x86-64-result - name: Copy AppImage file to root run: | for file in appimage-x86-64-result/*; do if [[ $file == *.AppImage && $file != *.AppImage.zsync ]]; then cp "$file" result.AppImage fi done - name: Upload Release Asset (AppImage) uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: result.AppImage asset_name: LocalSend-${{ needs.build.outputs.version }}-linux-x86-64.AppImage asset_content_type: application/x-appimage # WINDOWS ZIP (x86_64) - name: Download windows zip file uses: actions/download-artifact@v7 with: name: windows-zip-x86-64-result path: windows-zip-x86-64-result - name: Copy zip file to root run: cp windows-zip-x86-64-result/*.zip result.zip - name: Upload Release Asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.draft_release.outputs.upload_url }} asset_path: result.zip asset_name: LocalSend-${{ needs.build.outputs.version }}-windows-x86-64.zip asset_content_type: application/zip