feat: Add GitHub Actions workflows for building and releasing Android, iOS, Linux, and Windows applications

This commit is contained in:
2025-08-27 11:06:04 +02:00
parent 8cb163d969
commit fe1acd8669
5 changed files with 1127 additions and 0 deletions

69
.github/workflows/android-build.yml vendored Normal file
View File

@@ -0,0 +1,69 @@
# .github/workflows/release_apk_github.yml
name: Build Android Release
on:
release:
types: [published]
jobs:
build:
name: Build Android Release for GitHub
runs-on: ubuntu-latest
if: github.repository_owner == 'vleeuwenmenno' && contains(github.server_url, 'github.com')
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
- name: Install dependencies
run: flutter pub get
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Build release APK
run: flutter build apk --release
- name: Extract version
id: version
run: |
APP_VERSION=$(grep 'version:' pubspec.yaml | sed 's/version: //g' | sed 's/+.*//g')
echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV
- name: Rename APK
run: |
mv build/app/outputs/flutter-apk/app-release.apk supplements_${{ env.APP_VERSION }}_android.apk
- name: Build debug APK
run: flutter build apk --debug
- name: Rename Debug APK
run: |
mv build/app/outputs/flutter-apk/app-debug.apk supplements_${{ env.APP_VERSION }}_debug.apk
- name: Debug release information
run: |
echo "Release tag: ${{ github.event.release.tag_name }}"
echo "Release name: ${{ github.event.release.name }}"
echo "Release URL: ${{ github.event.release.html_url }}"
echo "App version: ${{ env.APP_VERSION }}"
- name: Upload APKs to GitHub Release
run: |
gh release upload "${{ github.event.release.tag_name }}" "supplements_${{ env.APP_VERSION }}_android.apk" --clobber
gh release upload "${{ github.event.release.tag_name }}" "supplements_${{ env.APP_VERSION }}_debug.apk" --clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

95
.github/workflows/ios-build.yml vendored Normal file
View File

@@ -0,0 +1,95 @@
# .github/workflows/ios-build-github.yml
name: Build iOS Release
on:
release:
types: [published]
jobs:
build:
name: Build and Upload iOS Release
runs-on: macos-14
if: github.repository_owner == 'vleeuwenmenno'
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Print Release Info
run: |
echo "Release Tag: ${{ github.event.release.tag_name }}"
echo "Release Name: ${{ github.event.release.name }}"
echo "GitHub Token exists: ${{ secrets.GITHUB_TOKEN != '' }}"
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
- name: Enable iOS support
run: flutter config --enable-ios
- name: Cache CocoaPods
uses: actions/cache@v4
with:
path: |
~/.cocoapods/repos
ios/Pods
key: ${{ runner.os }}-pods-${{ hashFiles('ios/Podfile.lock') }}
restore-keys: |
${{ runner.os }}-pods-
- name: Update CocoaPods repository
run: |
echo "Updating CocoaPods repository..."
pod repo update --silent
if [ $? -eq 0 ]; then
echo "CocoaPods repository updated successfully"
else
echo "Failed to update CocoaPods repository"
exit 1
fi
- name: Get dependencies
run: flutter pub get
- name: Extract version
id: version
run: |
APP_VERSION=$(grep 'version:' pubspec.yaml | sed 's/version: //g' | sed 's/+.*//g')
echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV
echo "App version: $APP_VERSION"
- name: Set up Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
# Updated build steps start here
- name: Build iOS app (unsigned)
run: |
flutter build ios --release --no-codesign
echo "Built .app location: $(pwd)/build/ios/iphoneos/Runner.app"
- name: Create unsigned IPA
run: |
mkdir Payload
cp -r build/ios/iphoneos/Runner.app Payload/
zip -r supplements_${{ env.APP_VERSION }}_ios_unsigned.ipa Payload
echo "Created unsigned IPA: $(pwd)/supplements_${{ env.APP_VERSION }}_ios_unsigned.ipa"
- name: Upload IPA to GitHub Release
run: |
gh release upload "${{ github.event.release.tag_name }}" \
"supplements_${{ env.APP_VERSION }}_ios_unsigned.ipa" \
--clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: ios-unsigned-ipa
path: supplements_${{ env.APP_VERSION }}_ios_unsigned.ipa
retention-days: 30

184
.github/workflows/linux-build.yml vendored Normal file
View File

@@ -0,0 +1,184 @@
# .github/workflows/linux-build-github.yml
name: Build Linux Release
on:
release:
types: [published]
jobs:
build:
name: Build and Upload Linux Release
runs-on: ubuntu-22.04
if: github.repository_owner == 'vleeuwenmenno' && contains(github.server_url, 'github.com')
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
- name: Enable Linux desktop support
run: flutter config --enable-linux-desktop
- name: Install Linux dependencies
run: |
# Fix GPG key issues
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 871920D1991BC93C
sudo apt-get update -y
# Install dependencies needed for Flutter Linux builds and appimage-builder
sudo apt-get install -y clang cmake git ninja-build pkg-config libgtk-3-dev liblzma-dev libstdc++-12-dev \
python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace pipx squashfs-tools zsync \
python3-venv python3-dev appstream
- name: Get dependencies
run: flutter pub get
- name: Build Linux release
run: flutter build linux --release
- name: Extract version
id: version
run: |
APP_VERSION=$(grep 'version:' pubspec.yaml | sed 's/version: //g' | sed 's/+.*//g')
echo "APP_VERSION=$APP_VERSION" >> $GITHUB_ENV
- name: Zip bundle directory
run: |
cd build/linux/x64/release
zip -r ../../../../supplements_${{ env.APP_VERSION }}_amd64_linux.zip bundle/*
cd ../../../../ # Go back to the root directory
- name: Download and extract AppImageTool
run: |
wget -O appimagetool-x86_64.AppImage https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool-x86_64.AppImage
# Extract AppImageTool to avoid FUSE dependency issues in containers
./appimagetool-x86_64.AppImage --appimage-extract
# The extracted tool will be in squashfs-root/AppRun
- name: Create AppDir structure using Flutter bundle
run: |
# Verify Flutter build exists
echo "Verifying Flutter build..."
if [[ ! -d "build/linux/x64/release/bundle" ]]; then
echo "Error: Flutter build directory not found!"
ls -la build/linux/x64/release/ || echo "Release directory doesn't exist"
exit 1
fi
if [[ ! -f "build/linux/x64/release/bundle/supplements" ]]; then
echo "Error: supplements executable not found!"
ls -la build/linux/x64/release/bundle/
exit 1
fi
# Create AppDir and copy the entire Flutter bundle
echo "Creating AppDir with Flutter bundle..."
mkdir -p AppDir
cp -r build/linux/x64/release/bundle AppDir/
# Create required directories for AppImage structure
mkdir -p AppDir/usr/share/applications
mkdir -p AppDir/usr/share/icons/hicolor/64x64/apps
# Copy icon
echo "Copying application icon..."
if [[ -f "android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png" ]]; then
# Copy to standard location
cp android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png AppDir/usr/share/icons/hicolor/64x64/apps/
# Also copy to AppDir root with the name referenced in desktop file
cp android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png AppDir/ic_launcher.png
else
echo "Warning: Icon not found, trying other locations..."
ICON_FILE=$(find android/app/src/main/res/ -name "ic_launcher.png" | head -1)
if [[ -n "$ICON_FILE" ]]; then
cp "$ICON_FILE" AppDir/usr/share/icons/hicolor/64x64/apps/
cp "$ICON_FILE" AppDir/ic_launcher.png
else
echo "No icon found"
fi
fi
# Create desktop file (AppImageTool looks for it in the root of AppDir)
echo "Creating desktop file..."
cat > AppDir/supplements.desktop << 'EOF'
[Desktop Entry]
Name=supplements
Exec=AppRun
Icon=ic_launcher
Type=Application
Categories=Utility;
EOF
# Also create it in the standard location for completeness
cp AppDir/supplements.desktop AppDir/usr/share/applications/supplements.desktop
# Create AppRun script that uses the Flutter bundle directly
echo "Creating AppRun script..."
cat > AppDir/AppRun << 'EOF'
#!/bin/bash
HERE="$(dirname "$(readlink -f "${0}")")"
cd "${HERE}/bundle"
exec "./supplements" "$@"
EOF
chmod +x AppDir/AppRun
echo "AppDir structure created successfully!"
echo "AppDir contents:"
ls -la AppDir/
echo "Bundle contents:"
ls -la AppDir/bundle/
echo "Desktop file verification:"
ls -la AppDir/*.desktop
echo "Icon verification:"
ls -la AppDir/usr/share/icons/hicolor/64x64/apps/
- name: Build AppImage manually
run: |
# Verify AppDir structure before building
echo "Verifying AppDir structure..."
if [[ ! -f "AppDir/AppRun" ]]; then
echo "Error: AppRun not found!"
exit 1
fi
if [[ ! -f "AppDir/bundle/supplements" ]]; then
echo "Error: supplements executable not found in AppDir/bundle/!"
exit 1
fi
# Build AppImage using extracted appimagetool (avoids FUSE issues)
echo "Building AppImage..."
ARCH=amd64 ./squashfs-root/AppRun AppDir supplements-latest-amd64.AppImage
# Check if AppImage was created successfully
if [[ -f "supplements-latest-amd64.AppImage" ]]; then
echo "AppImage created successfully!"
ls -la supplements-latest-amd64.AppImage
else
echo "Error: AppImage creation failed!"
exit 1
fi
- name: Debug release information
run: |
echo "Release tag: ${{ github.event.release.tag_name }}"
echo "Release name: ${{ github.event.release.name }}"
echo "Release URL: ${{ github.event.release.html_url }}"
echo "App version: ${{ env.APP_VERSION }}"
- name: Upload Linux Zip to GitHub Release
run: |
gh release upload "${{ github.event.release.tag_name }}" "supplements_${{ env.APP_VERSION }}_amd64_linux.zip" --clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload Linux AppImage to GitHub Release
run: |
gh release upload "${{ github.event.release.tag_name }}" "supplements-latest-amd64.AppImage" --clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

206
.github/workflows/windows-build.yml vendored Normal file
View File

@@ -0,0 +1,206 @@
# .github/workflows/windows-build-github.yml
name: Build Windows Release
on:
release:
types: [published]
jobs:
build:
name: Build Windows Release
runs-on: windows-latest
if: github.repository_owner == 'vleeuwenmenno' && contains(github.server_url, 'github.com')
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
- name: Enable Windows desktop support
run: flutter config --enable-windows-desktop
- name: Install dependencies
run: flutter pub get
- name: Build Windows release
run: flutter build windows --release
- name: Extract version
id: version
shell: pwsh
run: |
$version = (Get-Content pubspec.yaml | Select-String "version:" | ForEach-Object { $_.ToString().Split(' ')[1] }).Split('+')[0]
echo "APP_VERSION=$version" >> $env:GITHUB_ENV
echo "Version extracted: $version"
- name: Create Windows installer directory structure
shell: pwsh
run: |
# Create installer directory
New-Item -ItemType Directory -Force -Path "installer"
# Copy the built app
Copy-Item -Recurse "build\windows\x64\runner\Release\*" "installer\"
# Verify the executable exists
if (Test-Path "installer\supplements.exe") {
Write-Host "✓ supplements.exe found in installer directory"
} else {
Write-Host "✗ supplements.exe not found!"
Get-ChildItem "installer" -Recurse
exit 1
}
- name: Create portable zip
shell: pwsh
run: |
Compress-Archive -Path "installer\*" -DestinationPath "supplements_${{ env.APP_VERSION }}_windows_x64_portable.zip"
# Verify zip was created
if (Test-Path "supplements_${{ env.APP_VERSION }}_windows_x64_portable.zip") {
$size = (Get-Item "supplements_${{ env.APP_VERSION }}_windows_x64_portable.zip").Length / 1MB
Write-Host "✓ Portable zip created successfully ($([math]::Round($size, 2)) MB)"
} else {
Write-Host "✗ Failed to create portable zip"
exit 1
}
- name: Create NSIS installer script
shell: pwsh
run: |
$nsisScript = @"
!define APP_NAME "supplements"
!define APP_VERSION "${{ env.APP_VERSION }}"
!define APP_PUBLISHER "vleeuwenmenno"
!define APP_DESCRIPTION "A ComfyUI client with sync capabilities"
!define APP_EXECUTABLE "supplements.exe"
!include "MUI2.nsh"
Name "`${APP_NAME} `${APP_VERSION}"
OutFile "supplements_`${APP_VERSION}_windows_x64_installer.exe"
InstallDir "`$PROGRAMFILES64\`${APP_NAME}"
InstallDirRegKey HKLM "Software\`${APP_NAME}" "InstallDir"
RequestExecutionLevel admin
!define MUI_ABORTWARNING
!define MUI_ICON "`${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
!define MUI_UNICON "`${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE "installer\LICENSE"
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE "English"
Section "Install"
SetOutPath "`$INSTDIR"
File /r "installer\*"
WriteRegStr HKLM "Software\`${APP_NAME}" "InstallDir" "`$INSTDIR"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "DisplayName" "`${APP_NAME}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "UninstallString" "`$INSTDIR\Uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "DisplayVersion" "`${APP_VERSION}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "Publisher" "`${APP_PUBLISHER}"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "DisplayIcon" "`$INSTDIR\`${APP_EXECUTABLE}"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}" "NoRepair" 1
CreateDirectory "`$SMPROGRAMS\`${APP_NAME}"
CreateShortcut "`$SMPROGRAMS\`${APP_NAME}\`${APP_NAME}.lnk" "`$INSTDIR\`${APP_EXECUTABLE}"
CreateShortcut "`$SMPROGRAMS\`${APP_NAME}\Uninstall.lnk" "`$INSTDIR\Uninstall.exe"
CreateShortcut "`$DESKTOP\`${APP_NAME}.lnk" "`$INSTDIR\`${APP_EXECUTABLE}"
WriteUninstaller "`$INSTDIR\Uninstall.exe"
SectionEnd
Section "Uninstall"
Delete "`$INSTDIR\Uninstall.exe"
RMDir /r "`$INSTDIR"
RMDir /r "`$SMPROGRAMS\`${APP_NAME}"
Delete "`$DESKTOP\`${APP_NAME}.lnk"
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\`${APP_NAME}"
DeleteRegKey HKLM "Software\`${APP_NAME}"
SectionEnd
"@
$nsisScript | Out-File -FilePath "installer.nsi" -Encoding UTF8
Write-Host "✓ NSIS script created"
- name: Create dummy LICENSE file
shell: pwsh
run: |
$license = @"
MIT License
Copyright (c) 2025 vleeuwenmenno
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
"@
$license | Out-File -FilePath "installer\LICENSE" -Encoding UTF8
Write-Host "✓ LICENSE file created"
- name: Build NSIS installer
uses: joncloud/makensis-action@v4.1
with:
script-file: "installer.nsi"
- name: Verify installer creation
shell: pwsh
run: |
# Verify installer was created
if (Test-Path "supplements_${{ env.APP_VERSION }}_windows_x64_installer.exe") {
$size = (Get-Item "supplements_${{ env.APP_VERSION }}_windows_x64_installer.exe").Length / 1MB
Write-Host "✓ NSIS installer created successfully ($([math]::Round($size, 2)) MB)"
} else {
Write-Host "✗ Failed to create NSIS installer"
Get-ChildItem . -Filter "*.exe" | ForEach-Object { Write-Host "Found: $($_.Name)" }
exit 1
}
- name: Debug release information
run: |
echo "Release tag: ${{ github.event.release.tag_name }}"
echo "Release name: ${{ github.event.release.name }}"
echo "Release URL: ${{ github.event.release.html_url }}"
echo "App version: ${{ env.APP_VERSION }}"
- name: Upload Windows builds to GitHub Release
shell: pwsh
run: |
gh release upload "${{ github.event.release.tag_name }}" "supplements_${{ env.APP_VERSION }}_windows_x64_portable.zip" --clobber
gh release upload "${{ github.event.release.tag_name }}" "supplements_${{ env.APP_VERSION }}_windows_x64_installer.exe" --clobber
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}