Merge pull request #226 from IRedDragonICY/dependabot/npm_and_yarn/ty… #40
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Pre-Release on Push | |
| on: | |
| push: | |
| branches: [ main ] | |
| workflow_dispatch: | |
| env: | |
| RELEASE_TAG: pre-${{ github.run_number }}-${{ github.sha }} | |
| permissions: | |
| contents: write | |
| jobs: | |
| prerelease: | |
| name: Build and Pre-Release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Restore Next.js build cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: .next/cache | |
| key: ${{ runner.os }}-nextjs-${{ hashFiles('package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-nextjs- | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Build | |
| run: npm run build | |
| env: | |
| NEXT_TELEMETRY_DISABLED: '1' | |
| - name: Upload web build folder (.next) | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: web-build | |
| path: | | |
| .next/** | |
| public/** | |
| package.json | |
| package-lock.json | |
| next.config.ts | |
| tsconfig.json | |
| - name: Generate changelog | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| SERVER_URL="${GITHUB_SERVER_URL:-https://github.com}" | |
| REPO="${GITHUB_REPOSITORY}" | |
| LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| echo "## Changes" > release_notes.md | |
| if [ -z "$LAST_TAG" ]; then | |
| echo "_Initial pre-release; showing last 50 commits._" >> release_notes.md | |
| LOG=$(git log --pretty=format:'%h|%s|%an' -n 50) | |
| else | |
| echo "_Changes since $LAST_TAG._" >> release_notes.md | |
| LOG=$(git log "$LAST_TAG"..HEAD --pretty=format:'%h|%s|%an') | |
| fi | |
| echo "" >> release_notes.md | |
| gen_section() { # title pattern | |
| local TITLE="$1" | |
| local PATTERN="$2" | |
| local BODY | |
| BODY=$(echo "$LOG" | grep -E "\|$PATTERN" || true) | |
| if [ -n "$BODY" ]; then | |
| echo "### $TITLE" >> release_notes.md | |
| echo "$BODY" | while IFS='|' read -r h s a; do echo "- [**$h**](${SERVER_URL}/${REPO}/commit/$h) $s ($a)"; done >> release_notes.md | |
| echo "" >> release_notes.md | |
| fi | |
| } | |
| gen_section "Features" 'feat(\(|:|!)' | |
| gen_section "Fixes" 'fix(\(|:|!)' | |
| gen_section "Performance" 'perf(\(|:|!)' | |
| gen_section "Docs" 'docs(\(|:|!)' | |
| gen_section "Chores" 'chore(\(|:|!)' | |
| # Others = everything not matched above | |
| OTHER=$(echo "$LOG" | grep -Ev "\|(feat|fix|perf|docs|chore)(\(|:|!)" || true) | |
| if [ -n "$OTHER" ]; then | |
| echo "### Others" >> release_notes.md | |
| echo "$OTHER" | while IFS='|' read -r h s a; do echo "- [**$h**](${SERVER_URL}/${REPO}/commit/$h) $s ($a)"; done >> release_notes.md | |
| echo "" >> release_notes.md | |
| fi | |
| - name: Create/Update Pre-Release (no web zip) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ env.RELEASE_TAG }} | |
| name: Pre-Release ${{ github.run_number }} (${{ github.sha }}) | |
| body_path: release_notes.md | |
| prerelease: true | |
| make_latest: true | |
| tauri-windows: | |
| name: Tauri Windows (x64/x86) | |
| needs: prerelease | |
| runs-on: windows-latest | |
| strategy: | |
| matrix: | |
| arch: [x64, x86] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Generate Tauri icons from SVG | |
| shell: pwsh | |
| run: | | |
| if (Test-Path out/icon.svg) { $src = 'out/icon.svg' } else { $src = 'public/icon.svg' } | |
| if (-not (Test-Path $src)) { throw "icon.svg not found at $src" } | |
| npx tauri icon $src -o src-tauri/icons | cat | |
| - name: Build static web (export) | |
| run: npm run tauri:export | |
| - name: Discover version | |
| shell: pwsh | |
| run: | | |
| $json = Get-Content src-tauri/tauri.conf.json | ConvertFrom-Json | |
| echo "APP_VERSION=$($json.version)" >> $Env:GITHUB_ENV | |
| echo "PRODUCT_NAME=$($json.productName)" >> $Env:GITHUB_ENV | |
| - name: Add 32-bit Rust target (if needed) | |
| if: matrix.arch == 'x86' | |
| run: rustup target add i686-pc-windows-msvc | |
| - name: Build Tauri (portable + MSI installer) | |
| run: | | |
| if [ "${{ matrix.arch }}" = "x86" ]; then npx tauri build --target i686-pc-windows-msvc; else npm run tauri:build; fi | |
| shell: bash | |
| - name: Rename Windows artifacts | |
| shell: pwsh | |
| run: | | |
| $arch = if ('${{ matrix.arch }}' -eq 'x86') { 'x86' } else { 'x64' } | |
| $ver = "$Env:APP_VERSION" | |
| $outDir = if ($arch -eq 'x86') { 'src-tauri/target/i686-pc-windows-msvc/release' } else { 'src-tauri/target/release' } | |
| $exe = Get-ChildItem -Path $outDir -Filter *.exe | Select-Object -First 1 | |
| if ($exe) { Copy-Item $exe.FullName "booruprompt-$ver-win-$arch.exe" } | |
| $msiDir = if ($arch -eq 'x86') { 'src-tauri/target/i686-pc-windows-msvc/release/bundle/msi' } else { 'src-tauri/target/release/bundle/msi' } | |
| $msi = Get-ChildItem -Path $msiDir -Filter *.msi | Select-Object -First 1 | |
| if ($msi) { Copy-Item $msi.FullName "booruprompt-$ver-win-$arch.msi" } | |
| - name: Upload Windows artifacts (exe/msi) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ env.RELEASE_TAG }} | |
| files: | | |
| booruprompt-${{ env.APP_VERSION }}-win-${{ matrix.arch }}.exe | |
| booruprompt-${{ env.APP_VERSION }}-win-${{ matrix.arch }}.msi | |
| fail_on_unmatched_files: false | |
| tauri-linux: | |
| name: Tauri Linux Portable | |
| needs: prerelease | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Linux build deps | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev patchelf | |
| sudo apt-get install -y libwebkit2gtk-4.1-dev || sudo apt-get install -y libwebkit2gtk-4.0-dev | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Cache Rust | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Generate Tauri icons from SVG | |
| run: | | |
| set -e | |
| SRC="out/icon.svg" | |
| if [ ! -f "$SRC" ]; then SRC="public/icon.svg"; fi | |
| if [ ! -f "$SRC" ]; then echo "icon.svg not found" && exit 1; fi | |
| npx tauri icon "$SRC" -o src-tauri/icons | cat | |
| - name: Build static web (export) | |
| run: npm run tauri:export | |
| - name: Build Tauri (portable + AppImage + deb) | |
| run: npm run tauri:build | |
| - name: Discover version | |
| run: | | |
| node -e "const fs=require('fs');const j=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8'));console.log('APP_VERSION='+j.version)" >> $GITHUB_ENV | |
| - name: Rename Linux artifacts | |
| run: | | |
| set -e | |
| VER="$APP_VERSION" | |
| BIN="src-tauri/target/release/booruprompt" | |
| if [ ! -f "$BIN" ]; then BIN=$(ls -1 src-tauri/target/release/* | head -n 1); fi | |
| if [ ! -f "$BIN" ]; then echo "Linux binary not found" && ls -la src-tauri/target/release || true && exit 1; fi | |
| cp "$BIN" booruprompt-$VER-linux-x64 | |
| for f in src-tauri/target/release/bundle/appimage/*.AppImage; do cp "$f" booruprompt-$VER-linux-x64.AppImage; done | |
| for f in src-tauri/target/release/bundle/deb/*.deb; do cp "$f" booruprompt-$VER-linux-amd64.deb; done | |
| - name: Upload Linux artifacts (bin/AppImage/deb) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ env.RELEASE_TAG }} | |
| files: | | |
| booruprompt-${{ env.APP_VERSION }}-linux-x64 | |
| booruprompt-${{ env.APP_VERSION }}-linux-x64.AppImage | |
| booruprompt-${{ env.APP_VERSION }}-linux-amd64.deb | |
| fail_on_unmatched_files: false | |
| tauri-android: | |
| name: Tauri Android (per-ABI APKs + AAB) | |
| needs: prerelease | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| - 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: Install Android packages | |
| run: | | |
| yes | sdkmanager --licenses > /dev/null | |
| sdkmanager --install "platform-tools" "platforms;android-33" "platforms;android-34" "build-tools;34.0.0" "build-tools;33.0.2" "cmake;3.22.1" "ndk;25.1.8937393" | |
| - name: Set Android env (NDK_HOME, ANDROID_HOME) | |
| run: | | |
| echo "ANDROID_HOME=$ANDROID_SDK_ROOT" >> $GITHUB_ENV | |
| NDK_DIR=$(ls -1d "$ANDROID_SDK_ROOT"/ndk/* | sort -V | tail -n 1) | |
| if [ -z "$NDK_DIR" ]; then echo "NDK not found under $ANDROID_SDK_ROOT/ndk" && exit 1; fi | |
| echo "NDK_HOME=$NDK_DIR" >> $GITHUB_ENV | |
| echo "ANDROID_NDK_HOME=$NDK_DIR" >> $GITHUB_ENV | |
| - name: Setup Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Add Android Rust targets | |
| run: | | |
| rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Generate Tauri icons from SVG | |
| run: | | |
| set -e | |
| SRC="out/icon.svg" | |
| if [ ! -f "$SRC" ]; then SRC="public/icon.svg"; fi | |
| if [ ! -f "$SRC" ]; then echo "icon.svg not found" && exit 1; fi | |
| npx tauri icon "$SRC" -o src-tauri/icons | cat | |
| - name: Build static web (export) | |
| run: npm run tauri:export | |
| - name: Clean previous Android project (if any) | |
| run: rm -rf src-tauri/gen/android || true | |
| - name: Init Android project | |
| env: | |
| ANDROID_SDK_ROOT: ${{ env.ANDROID_SDK_ROOT }} | |
| ANDROID_HOME: ${{ env.ANDROID_SDK_ROOT }} | |
| NDK_HOME: ${{ env.NDK_HOME }} | |
| ANDROID_NDK_HOME: ${{ env.ANDROID_NDK_HOME }} | |
| run: | | |
| npx tauri android init --ci | |
| test -d src-tauri/gen/android || (echo "Init did not generate project" && exit 1) | |
| - name: Verify Android project exists | |
| run: | | |
| test -d src-tauri/gen/android || (ls -la src-tauri/gen || true; echo "Android project missing"; exit 1) | |
| - name: Warm-up Tauri (generate gradle settings) | |
| env: | |
| ANDROID_SDK_ROOT: ${{ env.ANDROID_SDK_ROOT }} | |
| ANDROID_HOME: ${{ env.ANDROID_SDK_ROOT }} | |
| NDK_HOME: ${{ env.NDK_HOME }} | |
| ANDROID_NDK_HOME: ${{ env.ANDROID_NDK_HOME }} | |
| TAURI_CLI_NO_SERVER: '1' | |
| run: | | |
| npx tauri android init --ci | cat || true | |
| - name: Build Android (release) — per-ABI APKs + AAB | |
| env: | |
| ANDROID_SDK_ROOT: ${{ env.ANDROID_SDK_ROOT }} | |
| ANDROID_HOME: ${{ env.ANDROID_SDK_ROOT }} | |
| NDK_HOME: ${{ env.NDK_HOME }} | |
| ANDROID_NDK_HOME: ${{ env.ANDROID_NDK_HOME }} | |
| TAURI_CLI_NO_SERVER: '1' | |
| RUSTFLAGS: '-C strip=symbols' | |
| run: | | |
| npx tauri android build --ci --apk --aab --split-per-abi --target aarch64 --target armv7 --target i686 --target x86_64 | cat | |
| - name: Discover version | |
| run: | | |
| node -e "const fs=require('fs');const j=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8'));console.log('APP_VERSION='+j.version)" >> $GITHUB_ENV | |
| - name: Rename Android artifacts (release) | |
| run: | | |
| set -e | |
| VER="$APP_VERSION" | |
| OUT=src-tauri/gen/android/app/build/outputs | |
| # Map arch names from Gradle/Tauri to Android ABI naming | |
| map_arch() { | |
| case "$1" in | |
| arm) echo "armeabi-v7a" ;; | |
| arm64) echo "arm64-v8a" ;; | |
| x86) echo "x86" ;; | |
| x86_64) echo "x86_64" ;; | |
| *) echo "$1" ;; | |
| esac | |
| } | |
| # Per-ABI APKs (release), handle -unsigned suffix | |
| for dir in "$OUT"/apk/*/release; do | |
| [ -d "$dir" ] || continue | |
| arch_dir=$(basename "$(dirname "$dir")") | |
| abi=$(map_arch "$arch_dir") | |
| apk_path="" | |
| if ls "$dir"/app-*-release-unsigned.apk >/dev/null 2>&1; then | |
| apk_path=$(ls -1 "$dir"/app-*-release-unsigned.apk | head -n 1) | |
| elif ls "$dir"/app-*-release.apk >/dev/null 2>&1; then | |
| apk_path=$(ls -1 "$dir"/app-*-release.apk | head -n 1) | |
| fi | |
| if [ -n "$apk_path" ]; then | |
| cp "$apk_path" "booruprompt-$VER-android-$abi.apk" | |
| fi | |
| done | |
| # Per-ABI AABs (release) | |
| for dir in "$OUT"/bundle/*Release; do | |
| [ -d "$dir" ] || continue | |
| name=$(basename "$dir") # e.g., armRelease, arm64Release, x86Release, x86_64Release | |
| arch=${name%Release} | |
| abi=$(map_arch "$arch") | |
| if ls "$dir"/app-*-release.aab >/dev/null 2>&1; then | |
| aab_path=$(ls -1 "$dir"/app-*-release.aab | head -n 1) | |
| cp "$aab_path" "booruprompt-$VER-android-$abi.aab" | |
| fi | |
| done | |
| # Universal AAB (release) if present | |
| if ls "$OUT"/bundle/universalRelease/app-*-release.aab >/dev/null 2>&1; then | |
| cp "$OUT"/bundle/universalRelease/app-*-release.aab "booruprompt-$VER-android-universal.aab" | |
| fi | |
| - name: Upload Android artifacts (APK/AAB) | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ env.RELEASE_TAG }} | |
| files: | | |
| booruprompt-${{ env.APP_VERSION }}-android-armeabi-v7a.apk | |
| booruprompt-${{ env.APP_VERSION }}-android-arm64-v8a.apk | |
| booruprompt-${{ env.APP_VERSION }}-android-x86.apk | |
| booruprompt-${{ env.APP_VERSION }}-android-x86_64.apk | |
| booruprompt-${{ env.APP_VERSION }}-android-armeabi-v7a.aab | |
| booruprompt-${{ env.APP_VERSION }}-android-arm64-v8a.aab | |
| booruprompt-${{ env.APP_VERSION }}-android-x86.aab | |
| booruprompt-${{ env.APP_VERSION }}-android-x86_64.aab | |
| booruprompt-${{ env.APP_VERSION }}-android-universal.aab | |
| fail_on_unmatched_files: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |