name: Build & Release on: push: tags: - 'v*' workflow_dispatch: inputs: version: description: 'Version to build (e.g., v1.0.0)' required: false env: RUST_BACKTRACE: 1 CARGO_TERM_COLOR: always jobs: test: name: Run Tests runs-on: linux/amd64 container: image: gitea.tourolle.paris/dtourolle/jellytau-builder:latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Cache Rust dependencies uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git src-tauri/target key: ${{ runner.os }}-cargo-host-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo-host- - name: Cache Node dependencies uses: actions/cache@v3 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: Install dependencies run: bun install - name: Run frontend tests run: | bunx svelte-kit sync bun run test --run continue-on-error: false - name: Run Rust tests run: bun run test:rust continue-on-error: false - name: Check TypeScript run: bun run check continue-on-error: false build-linux: name: Build Linux runs-on: linux/amd64 needs: test container: image: gitea.tourolle.paris/dtourolle/jellytau-builder:latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Cache Rust dependencies uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git src-tauri/target key: ${{ runner.os }}-cargo-host-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo-host- - name: Cache Node dependencies uses: actions/cache@v3 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: Install dependencies run: bun install - name: Build for Linux run: bun run tauri build env: TAURI_SKIP_UPDATER: true - name: Prepare Linux artifacts run: | mkdir -p dist/linux # Copy AppImage if [ -f "src-tauri/target/release/bundle/appimage/jellytau_"*.AppImage ]; then cp src-tauri/target/release/bundle/appimage/jellytau_*.AppImage dist/linux/ fi # Copy .deb if built if [ -f "src-tauri/target/release/bundle/deb/jellytau_"*.deb ]; then cp src-tauri/target/release/bundle/deb/jellytau_*.deb dist/linux/ fi ls -lah dist/linux/ - name: Upload Linux build artifact uses: actions/upload-artifact@v3 with: name: jellytau-linux path: dist/linux/ retention-days: 30 build-android: name: Build Android runs-on: linux/amd64 needs: test container: image: gitea.tourolle.paris/dtourolle/jellytau-builder:latest env: ANDROID_HOME: /opt/android-sdk ANDROID_SDK_ROOT: /opt/android-sdk ANDROID_NDK_HOME: /opt/android-sdk/ndk/27.0.11902837 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Cache Rust dependencies uses: actions/cache@v3 with: path: | ~/.cargo/registry ~/.cargo/git src-tauri/target key: ${{ runner.os }}-cargo-android-${{ hashFiles('**/Cargo.lock') }} restore-keys: | ${{ runner.os }}-cargo-android- - name: Cache Node dependencies uses: actions/cache@v3 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('**/bun.lock') }} restore-keys: | ${{ runner.os }}-bun- - name: Install dependencies run: bun install - name: Set app version from tag run: | REF="${GITHUB_REF#refs/tags/v}" VERSION="${REF#refs/heads/}" # On non-tag runs keep whatever is in tauri.conf.json if echo "$GITHUB_REF" | grep -q '^refs/tags/v'; then echo "Setting version to $VERSION" sed -i "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" src-tauri/tauri.conf.json fi grep '"version"' src-tauri/tauri.conf.json - name: Initialize Android project run: bun run tauri android init - name: Sync custom Android sources & gradle config run: ./scripts/sync-android-sources.sh - name: Write signing keystore run: | echo "${{ secrets.ANDROID_KEYSTORE_BASE64 }}" | base64 -d > "$RUNNER_TEMP/jellytau-release.jks" cat > src-tauri/gen/android/keystore.properties <> $GITHUB_OUTPUT echo "RELEASE_NAME=JellyTau ${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT - name: Download Linux artifacts uses: actions/download-artifact@v3 with: name: jellytau-linux path: artifacts/linux/ - name: Download Android artifacts uses: actions/download-artifact@v3 with: name: jellytau-android path: artifacts/android/ - name: Prepare release notes id: release_notes run: | VERSION="${{ steps.tag_name.outputs.VERSION }}" echo "## JellyTau $VERSION Release" > release_notes.md echo "" >> release_notes.md echo "### Downloads" >> release_notes.md echo "" >> release_notes.md echo "#### Linux" >> release_notes.md echo "- **AppImage** - Run directly on most Linux distributions" >> release_notes.md echo "- **DEB** - Install via \`sudo dpkg -i jellytau_*.deb\` (Ubuntu/Debian)" >> release_notes.md echo "" >> release_notes.md echo "#### Android" >> release_notes.md echo "- **APK** - Install via \`adb install jellytau-release.apk\` or sideload via file manager" >> release_notes.md echo "- **AAB** - Upload to Google Play Console or testing platforms" >> release_notes.md echo "" >> release_notes.md echo "### What's New" >> release_notes.md echo "" >> release_notes.md echo "See [CHANGELOG.md](CHANGELOG.md) for detailed changes." >> release_notes.md echo "" >> release_notes.md echo "### Installation" >> release_notes.md echo "" >> release_notes.md echo "#### Linux (AppImage)" >> release_notes.md echo "\`\`\`bash" >> release_notes.md echo "chmod +x jellytau_*.AppImage" >> release_notes.md echo "./jellytau_*.AppImage" >> release_notes.md echo "\`\`\`" >> release_notes.md echo "" >> release_notes.md echo "#### Linux (DEB)" >> release_notes.md echo "\`\`\`bash" >> release_notes.md echo "sudo dpkg -i jellytau_*.deb" >> release_notes.md echo "jellytau" >> release_notes.md echo "\`\`\`" >> release_notes.md echo "" >> release_notes.md echo "#### Android" >> release_notes.md echo "- Sideload: Download APK and install via file manager or ADB" >> release_notes.md echo "- Play Store: Coming soon" >> release_notes.md echo "" >> release_notes.md echo "### Known Issues" >> release_notes.md echo "" >> release_notes.md echo "See [GitHub Issues](../../issues) for reported bugs." >> release_notes.md echo "" >> release_notes.md echo "### Requirements" >> release_notes.md echo "" >> release_notes.md echo "**Linux:**" >> release_notes.md echo "- 64-bit Linux system" >> release_notes.md echo "- GLIBC 2.29+" >> release_notes.md echo "" >> release_notes.md echo "**Android:**" >> release_notes.md echo "- Android 8.0 or higher" >> release_notes.md echo "- 50MB free storage" >> release_notes.md echo "" >> release_notes.md echo "---" >> release_notes.md echo "Built with Tauri, SvelteKit, and Rust" >> release_notes.md - name: Publish Gitea release & upload assets env: # GITEA_TOKEN (a PAT) is preferred; falls back to the auto-provided token. GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} AUTO_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -e command -v jq >/dev/null || { echo "❌ jq is required on the runner"; exit 1; } VERSION="${{ steps.tag_name.outputs.VERSION }}" API="${GITHUB_SERVER_URL}/api/v1" REPO="${GITHUB_REPOSITORY}" TOKEN="${GITEA_TOKEN:-$AUTO_TOKEN}" case "$VERSION" in *rc*|*beta*|*alpha*) PRE=true;; *) PRE=false;; esac PAYLOAD=$(jq -n \ --arg tag "$VERSION" \ --arg name "JellyTau $VERSION" \ --rawfile body release_notes.md \ --argjson pre "$PRE" \ '{tag_name:$tag, name:$name, body:$body, draft:false, prerelease:$pre}') echo "đŸ“Ļ Creating release $VERSION on $REPO" # -f drops on HTTP error; capture status so an existing release (409) is handled gracefully. HTTP=$(curl -sS -o resp.json -w '%{http_code}' -X POST "$API/repos/$REPO/releases" \ -H "Authorization: token $TOKEN" \ -H "Content-Type: application/json" \ -d "$PAYLOAD") if [ "$HTTP" = "201" ]; then RELEASE_ID=$(jq -r '.id' resp.json) elif [ "$HTTP" = "409" ]; then echo "â„šī¸ Release $VERSION already exists; fetching its id to upload assets" RELEASE_ID=$(curl -fsS "$API/repos/$REPO/releases/tags/$VERSION" \ -H "Authorization: token $TOKEN" | jq -r '.id') else echo "❌ Failed to create release (HTTP $HTTP):"; cat resp.json; exit 1 fi echo "Release id=$RELEASE_ID" for f in artifacts/android/* artifacts/linux/*; do [ -f "$f" ] || continue echo "âŦ†ī¸ Uploading $(basename "$f")" curl -fsS -X POST \ "$API/repos/$REPO/releases/$RELEASE_ID/assets?name=$(basename "$f")" \ -H "Authorization: token $TOKEN" \ -F "attachment=@$f" >/dev/null done echo "✅ Release $VERSION published with assets"