Skip to content

Add LICENSE

Add LICENSE #33

Workflow file for this run

name: Build All Platforms & Deploy
on:
push:
branches: ["master"]
workflow_dispatch:
permissions:
contents: write
pages: write
id-token: write
concurrency:
group: "deploy-all"
cancel-in-progress: true
jobs:
build-desktop:
name: Build Desktop Apps
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
name: linux
- os: windows-latest
target: x86_64-pc-windows-msvc
name: windows
- os: macos-latest
target: x86_64-apple-darwin
name: macos-intel
- os: macos-latest
target: aarch64-apple-darwin
name: macos-apple-silicon
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: "npm"
- name: Install Dependencies
run: npm install
- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Cache Rust Dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
src-tauri/target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install Linux Dependencies
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt update
sudo apt install -y libgtk-3-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: Install macOS Dependencies
if: matrix.os == 'macos-latest'
run: |
# Install genisoimage for DMG creation
brew install genisoimage || echo "genisoimage already installed or not needed"
- name: Debug Build Environment
run: |
echo "OS: ${{ matrix.os }}"
echo "Target: ${{ matrix.target }}"
echo "Node version: $(node --version)"
echo "npm version: $(npm --version)"
echo "Rust version: $(rustc --version)"
echo "Cargo version: $(cargo --version)"
if [ "${{ matrix.os }}" = "macos-latest" ]; then
echo "macOS version: $(sw_vers)"
echo "Available disk space: $(df -h)"
fi
shell: bash
- name: Build Tauri App
run: |
# Build based on platform
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
npx tauri build --target ${{ matrix.target }} --bundles deb,appimage
elif [ "${{ matrix.os }}" = "windows-latest" ]; then
npx tauri build --target ${{ matrix.target }} --bundles nsis,msi
elif [ "${{ matrix.os }}" = "macos-latest" ]; then
# Build only dmg for macOS
npx tauri build --target ${{ matrix.target }} --bundles dmg
fi
shell: bash
- name: List Build Output
run: |
echo "Build output structure:"
find src-tauri/target/${{ matrix.target }}/release/bundle -type f -name "*" 2>/dev/null | head -20 || echo "No bundle files found"
shell: bash
- name: Upload Release Artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.name }}-build
path: |
src-tauri/target/${{ matrix.target }}/release/bundle
!**/*.dSYM
if-no-files-found: warn
build-android:
name: Build Android APK
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22
cache: "npm"
- name: Install Dependencies
run: npm install
- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: "temurin"
java-version: "17"
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Cache Android Dependencies
uses: actions/cache@v4
with:
path: |
~/.android/cache
~/.gradle/caches
~/.gradle/wrapper
src-tauri/gen/android/.gradle
key: ${{ runner.os }}-android-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- name: Install Rust Toolchain
uses: dtolnay/rust-toolchain@stable
- name: Cache Rust Dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
src-tauri/target
key: ${{ runner.os }}-android-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Install Android Rust Targets
run: |
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
- name: Setup Android NDK
run: |
echo "ANDROID_NDK_HOME=$ANDROID_SDK_ROOT/ndk/27.2.12479018" >> $GITHUB_ENV
echo "NDK_HOME=$ANDROID_SDK_ROOT/ndk/27.2.12479018" >> $GITHUB_ENV
- name: Install Android NDK
run: |
sdkmanager "ndk;27.2.12479018"
- name: Initialize Android Project
run: |
# Remove existing Android project to avoid package name conflicts
if [ -d "src-tauri/gen/android" ]; then
echo "Removing existing Android project to avoid package conflicts..."
rm -rf src-tauri/gen/android
fi
echo "Initializing Android project..."
npx tauri android init
- name: Update Android Icons
run: |
echo "Regenerating Android icons with latest logo..."
npx tauri icon public/logo.png
echo "Android icons updated successfully!"
- name: Update Android Theme
run: |
echo "Updating Android theme to follow system theme..."
node update-android-theme.js
- name: Setup Android Signing
run: |
cd src-tauri/gen/android
echo "keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}" > keystore.properties
echo "password=${{ secrets.ANDROID_KEY_PASSWORD }}" >> keystore.properties
base64 -d <<< "${{ secrets.ANDROID_KEY_BASE64 }}" > $RUNNER_TEMP/keystore.jks
echo "storeFile=$RUNNER_TEMP/keystore.jks" >> keystore.properties
echo "Keystore properties configured:"
cat keystore.properties | sed 's/password=.*/password=***/'
- name: Build Signed Android APK (Release)
run: |
echo "Building signed APK..."
npx tauri android build --apk --split-per-abi
- name: Sign APKs with apksigner
run: |
echo "Signing APKs with apksigner..."
# Find and sign all unsigned APKs
find src-tauri/gen/android/app/build/outputs/apk -name "*-unsigned.apk" -type f | while read unsigned_apk; do
# Create signed APK filename
signed_apk="${unsigned_apk/-unsigned.apk/-signed.apk}"
echo "Signing: $unsigned_apk -> $signed_apk"
# Sign the APK
$ANDROID_HOME/build-tools/34.0.0/apksigner sign \
--ks $RUNNER_TEMP/keystore.jks \
--ks-key-alias ${{ secrets.ANDROID_KEY_ALIAS }} \
--ks-pass pass:${{ secrets.ANDROID_KEY_PASSWORD }} \
--key-pass pass:${{ secrets.ANDROID_KEY_PASSWORD }} \
--out "$signed_apk" \
"$unsigned_apk"
# Verify the signed APK
echo "Verifying signed APK: $signed_apk"
$ANDROID_HOME/build-tools/34.0.0/apksigner verify "$signed_apk"
if [ $? -eq 0 ]; then
echo "✅ Successfully signed and verified: $(basename "$signed_apk")"
else
echo "❌ Failed to verify: $(basename "$signed_apk")"
fi
done
- name: Verify APK Signing
run: |
echo "Verifying APK signing status..."
find src-tauri/gen/android/app/build/outputs/apk -name "*-signed.apk" -type f | while read apk; do
echo "Checking: $apk"
if command -v aapt &> /dev/null; then
aapt dump badging "$apk" | grep "package:" || true
fi
# Also check with jarsigner
if command -v jarsigner &> /dev/null; then
echo "Jarsigner verification:"
jarsigner -verify -verbose -certs "$apk" || true
fi
echo "---"
done
- name: List Android Build Output
run: |
echo "Contents of src-tauri/gen/android/app/build/outputs/apk:"
find src-tauri/gen/android/app/build/outputs/apk -name "*.apk" -type f || echo "No APK files found"
echo ""
echo "Signed APKs:"
find src-tauri/gen/android/app/build/outputs/apk -name "*-signed.apk" -type f || echo "No signed APK files found"
- name: Upload Signed Android APK
uses: actions/upload-artifact@v4
with:
name: android-build-signed
path: |
src-tauri/gen/android/app/build/outputs/apk/**/*-signed.apk
web:
name: Build Web & Deploy to GitHub Pages
runs-on: ubuntu-latest
needs: [build-desktop, build-android]
# Only run GitHub Pages deployment in the forked repository
if: github.repository == 'image-compressor/image-compressor.github.io'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
cache: "npm"
- name: Install dependencies
run: npm install
- name: Build web
run: npm run build
- name: Setup Pages
uses: actions/configure-pages@v3
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: "./dist"
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
release:
name: Release to GitHub
runs-on: ubuntu-latest
needs: [build-desktop, build-android]
# Always run release job regardless of which repository
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: ./artifacts
- name: Prepare release files
run: |
mkdir -p release-files
# Copy Android APKs (only signed ones)
find artifacts/android-build-signed -name "*-signed.apk" -type f -exec cp {} release-files/ \;
# Copy desktop builds
find artifacts/windows-build -name "*.exe" -type f -exec cp {} release-files/ \;
find artifacts/windows-build -name "*.msi" -type f -exec cp {} release-files/ \;
find artifacts/macos-intel-build -name "*.dmg" -type f -exec cp {} release-files/ \;
find artifacts/macos-apple-silicon-build -name "*.dmg" -type f -exec cp {} release-files/ \;
find artifacts/linux-build -name "*.deb" -type f -exec cp {} release-files/ \;
find artifacts/linux-build -name "*.AppImage" -type f -exec cp {} release-files/ \;
# List all files
echo "Release files:"
ls -la release-files/
- name: Generate release tag
id: tag
run: |
# Get version from package.json
VERSION=$(node -p "require('./package.json').version")
# Create a tag with project version and git SHA
TAG="v${VERSION}-$(echo ${{ github.sha }} | cut -c1-7)"
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "Generated tag: $TAG"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: "Release ${{ steps.tag.outputs.tag }}"
tag_name: ${{ steps.tag.outputs.tag }}
body: |
Automated release from commit ${{ github.sha }}
## Changes
- Built for all platforms (Windows, macOS, Linux, Android)
- Web deployment to GitHub Pages
## Downloads
- **Windows**: Download `.exe` or `.msi` files
- **macOS**: Download `.dmg` files (recommended installer)
- **Linux**: Download `.deb` or `.AppImage` files
- **Android**: Download `.apk` files for direct installation
files: |
release-files/*
draft: false
prerelease: false