Skip to content

Merge pull request #226 from IRedDragonICY/dependabot/npm_and_yarn/ty… #40

Merge pull request #226 from IRedDragonICY/dependabot/npm_and_yarn/ty…

Merge pull request #226 from IRedDragonICY/dependabot/npm_and_yarn/ty… #40

Workflow file for this run

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 }}