Skip to content

App Released - v1.0.2 #3

App Released - v1.0.2

App Released - v1.0.2 #3

Workflow file for this run

name: App Release
run-name: >-
${{
github.event_name == 'workflow_dispatch' && format('App Released - v{0}', github.event.inputs.tag) ||
github.event_name == 'repository_dispatch' && format('App Released - v{0}', github.event.client_payload.version || github.event.client_payload.tag) ||
format('App Released - {0}', github.ref_name)
}}
on:
push:
tags:
- '*' # Match all tags, not limited to v prefix
repository_dispatch:
types: [trigger-app-release]
workflow_dispatch:
inputs:
tag:
description: 'Tag Version (e.g. 1.0.0)'
required: true
type: string
disable-rust-cache:
description: 'Disable Rust cache (useful for troubleshooting build issues)'
required: false
type: boolean
default: false
jobs:
# Set version first
set-version:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.set_version.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set Version Variable
id: set_version
run: |
# Print debug info
echo "Event name: ${{ github.event_name }}"
# Always use version number without v prefix
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
VERSION="${{ github.event.inputs.tag }}"
elif [[ "${{ github.event_name }}" == "repository_dispatch" ]]; then
if [[ "${{ github.event.client_payload.version }}" != "" ]]; then
VERSION="${{ github.event.client_payload.version }}"
else
VERSION="${{ github.event.client_payload.tag }}"
fi
else
# Get version from tag (remove v prefix if present)
TAG="${GITHUB_REF_NAME}"
VERSION="${TAG#v}"
fi
# Ensure VERSION is not empty, default to 1.0.0
if [ -z "$VERSION" ]; then
echo "WARNING: Empty version, using default 1.0.0"
VERSION="1.0.0"
fi
echo "VERSION=$VERSION" >> $GITHUB_ENV
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Set version: $VERSION"
# Update Tauri Config Version
update-version:
runs-on: ubuntu-latest
needs: set-version
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Update Tauri Config Version
run: |
echo "Current version: ${{ needs.set-version.outputs.version }}"
# Update version using jq
jq '.version = "${{ needs.set-version.outputs.version }}"' app/src-tauri/tauri.conf.json > tmp.json && mv tmp.json app/src-tauri/tauri.conf.json
echo "Updated tauri.conf.json:"
cat app/src-tauri/tauri.conf.json
- name: Commit and Push Updated Version
run: |
git config --global user.name 'GitHub Actions'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add app/src-tauri/tauri.conf.json
if git diff --staged --quiet; then
echo "No changes to commit"
else
git commit -m "[ci skip] Update version to ${{ needs.set-version.outputs.version }}"
git push
echo "Pushed version update to repository"
fi
- name: Upload tauri.conf.json as artifact
uses: actions/upload-artifact@v4
with:
name: tauri-config
path: app/src-tauri/tauri.conf.json
# Desktop Platform Build Task
publish-desktop:
needs: [set-version, update-version]
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- platform: 'macos-latest' # Apple M-series chip (ARM)
args: '--target aarch64-apple-darwin'
- platform: 'macos-latest' # Intel chip Mac
args: '--target x86_64-apple-darwin'
- platform: 'ubuntu-22.04' # Linux Platform
args: ''
- platform: 'windows-latest' # Windows Platform (CPU)
args: ''
features: '--features whisper-cpu'
variant: 'cpu'
- platform: 'windows-latest' # Windows Platform (CUDA)
args: ''
features: '--features whisper-cuda'
variant: 'cuda'
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download tauri.conf.json
uses: actions/download-artifact@v4
with:
name: tauri-config
path: app/src-tauri/
- name: Install CUDA Toolkit (Windows CUDA)
if: matrix.platform == 'windows-latest' && matrix.variant == 'cuda'
uses: Jimver/cuda-toolkit@v0.2.24
id: cuda-toolkit
with:
cuda: '12.5.0'
method: 'network'
sub-packages: '[ "nvcc", "cudart", "cublas", "cublas_dev", "curand", "curand_dev", "visual_studio_integration", "thrust" ]'
- name: Set CUDA environment variables (Windows CUDA)
if: matrix.platform == 'windows-latest' && matrix.variant == 'cuda'
run: |
echo "Installed cuda version is: ${{steps.cuda-toolkit.outputs.cuda}}"
echo "Cuda install location: ${{steps.cuda-toolkit.outputs.CUDA_PATH}}"
echo "CUDA_PATH=${{steps.cuda-toolkit.outputs.CUDA_PATH}}" >> $GITHUB_ENV
echo "${{steps.cuda-toolkit.outputs.CUDA_PATH}}\bin" >> $GITHUB_PATH
nvcc -V
- name: Fix CUDA Visual Studio Integration (Windows CUDA)
if: matrix.platform == 'windows-latest' && matrix.variant == 'cuda'
run: |
$cudaPath = "${{steps.cuda-toolkit.outputs.CUDA_PATH}}"
echo "CUDA Path: $cudaPath"
# Source: CUDA Visual Studio integration files
$sourceDir = "$cudaPath\extras\visual_studio_integration\MSBuildExtensions"
echo "Source: $sourceDir"
# Find Visual Studio installation
$vsPaths = @(
"C:\Program Files\Microsoft Visual Studio\2022\Enterprise",
"C:\Program Files\Microsoft Visual Studio\2022\Community",
"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools"
)
foreach ($vsPath in $vsPaths) {
$destDir = "$vsPath\MSBuild\Microsoft\VC\v170\BuildCustomizations"
if (Test-Path $destDir) {
echo "Found VS at: $vsPath"
echo "Destination: $destDir"
if (Test-Path $sourceDir) {
echo "Copying CUDA integration files..."
Copy-Item "$sourceDir\*" $destDir -Force -Verbose
echo "Successfully copied CUDA integration files to $destDir"
} else {
echo "ERROR: Source directory not found: $sourceDir"
}
break
}
}
# Set environment variable for CMake to use CUDA toolset
echo "CMAKE_GENERATOR_TOOLSET=cuda=$cudaPath" >> $GITHUB_ENV
- name: Fix version format for Windows MSI
if: matrix.platform == 'windows-latest'
run: |
$versionJson = Get-Content -Path app/src-tauri/tauri.conf.json | ConvertFrom-Json
$currentVersion = $versionJson.version
if ($currentVersion -match '-(.+)$') {
$newVersion = $currentVersion -replace '-(.+)$', ''
$versionJson.version = $newVersion
$jsonContent = Get-Content -Path app/src-tauri/tauri.conf.json -Raw
$jsonContent = $jsonContent -replace '"version": "([^"]+)"', "`"version`": `"$newVersion`""
$jsonContent | Set-Content -Path app/src-tauri/tauri.conf.json -NoNewline
echo "Windows version $currentVersion changed to $newVersion"
} else {
echo "Version $currentVersion does not need to be modified"
}
- name: Install Ubuntu Dependencies
if: matrix.platform == 'ubuntu-22.04'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf libxdo-dev
- name: Setup Node Environment
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Increase Node.js memory limit
run: |
echo "NODE_OPTIONS=--max-old-space-size=4096" >> $GITHUB_ENV
- name: Install bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
components: ${{ matrix.platform == 'windows-latest' && 'rustfmt' || '' }}
- name: Rust Cache
if: github.event.inputs.disable-rust-cache != 'true'
uses: Swatinem/rust-cache@v2
with:
workspaces: app/src-tauri
cache-on-failure: true
- name: Cache Dependencies
uses: actions/cache@v3
with:
path: |
**/node_modules
key: ${{ runner.os }}-modules-${{ hashFiles('**/bun.lockb', '**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-modules-
- name: Install Dependencies
run: |
bun install --frozen-lockfile
# Copy CUDA config for CUDA builds (with installer checks)
- name: Use CUDA config (Windows CUDA)
if: matrix.platform == 'windows-latest' && matrix.variant == 'cuda'
run: |
Copy-Item "app\src-tauri\tauri.cuda.conf.json" "app\src-tauri\tauri.conf.json" -Force
echo "Using CUDA configuration with installer CUDA detection"
# Using official Tauri Action to build and publish
- name: Build and Publish Desktop App
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: 'app'
args: ${{ matrix.args }} ${{ matrix.features || '' }}
tagName: ${{ needs.set-version.outputs.version }}
releaseName: Blinko ${{ needs.set-version.outputs.version }}${{ matrix.variant && format(' ({0})', matrix.variant) || '' }}
releaseBody: "Under construction, full changelog will be updated after build completion..."
releaseDraft: false
prerelease: false
includeUpdaterJson: true
# Android Platform Build Task
publish-android:
needs: [set-version, update-version]
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Download tauri.conf.json
uses: actions/download-artifact@v4
with:
name: tauri-config
path: app/src-tauri/
- name: Setup JDK
uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '17'
- name: Setup Android SDK
uses: android-actions/setup-android@v3
- name: Install NDK
run: sdkmanager "ndk;27.0.11902837"
- name: Setup Node Environment
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Increase Node.js memory limit for Android build
run: |
echo "NODE_OPTIONS=--max-old-space-size=4096" >> $GITHUB_ENV
- name: Install Rust Stable
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-linux-android,armv7-linux-androideabi,i686-linux-android,x86_64-linux-android
- name: Rust Cache
if: github.event.inputs.disable-rust-cache != 'true'
uses: Swatinem/rust-cache@v2
with:
workspaces: app/src-tauri
cache-on-failure: true
- name: Cache Dependencies
uses: actions/cache@v3
with:
path: |
**/node_modules
key: ${{ runner.os }}-modules-${{ hashFiles('**/bun.lockb', '**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-modules-
- name: Install bun
uses: oven-sh/setup-bun@v1
with:
bun-version: latest
- name: Install Dependencies
run: |
bun install --frozen-lockfile
- name: Run Prisma Generate
run: bun run prisma:generate
- name: Configure Gradle Cache
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Upload Keystore File
run: |
# Create keystore directory
mkdir -p ~/.android
# Create keystore file
echo "${{ secrets.UPLOAD_KEYSTORE }}" | base64 --decode > ~/.android/upload-keystore.jks
# Create keystore.properties
mkdir -p app/src-tauri/gen/android
cat > app/src-tauri/gen/android/keystore.properties << EOF
password=106111
keyAlias=upload
storeFile=$HOME/.android/upload-keystore.jks
EOF
- name: Build Android App
run: |
cd app
bun run tauri:android:build
env:
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/27.0.11902837
- name: Rename Android App File
run: |
cd app/src-tauri/gen/android/app/build/outputs/apk/universal/release
VERSION="${{ needs.set-version.outputs.version }}"
echo "Original APK file:"
ls -la
# Rename APK file
mv app-universal-release.apk Blinko_${VERSION}_universal.apk
echo "Renamed APK file:"
ls -la
- name: Upload Android App to Existing Release
uses: softprops/action-gh-release@v1
with:
files: app/src-tauri/gen/android/app/build/outputs/apk/universal/release/Blinko_${{ needs.set-version.outputs.version }}_universal.apk
tag_name: ${{ needs.set-version.outputs.version }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Generate changelog after all builds are complete
generate-changelog:
runs-on: ubuntu-latest
needs: [set-version, publish-desktop, publish-android]
outputs:
changelog: ${{ steps.changelog.outputs.changes }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Fetch all tags
run: git fetch --tags
- name: Create Changelog
id: changelog
uses: loopwerk/tag-changelog@v1.3.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
config_file: .github/changelog/changelog.js
# Update release with final changelog
update-release:
runs-on: ubuntu-latest
needs: [set-version, generate-changelog]
permissions:
contents: write
steps:
- name: Update GitHub Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ needs.set-version.outputs.version }}
body: ${{ needs.generate-changelog.outputs.changelog }}
draft: false
prerelease: false
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Process notification content with AI
process-notification:
runs-on: ubuntu-latest
needs: [set-version, generate-changelog]
outputs:
chinese_message: ${{ steps.generate_chinese.outputs.message }}
english_message: ${{ steps.generate_english.outputs.message }}
steps:
- name: Generate Chinese message using OpenRouter AI
id: generate_chinese
uses: actions/github-script@v7
with:
script: |
try {
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer ${{ secrets.OPENROUTER_API_KEY }}',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'qwen/qwen-2.5-72b-instruct',
messages: [
{
role: 'user',
content: `请将以下发布通知翻译成简体中文,并格式化为Telegram纯文本消息(不要使用Markdown):
版本: ${{ needs.set-version.outputs.version }}
更新日志:
${{ needs.generate-changelog.outputs.changelog }}
下载链接: https://github.com/${{ github.repository }}/releases/tag/${{ needs.set-version.outputs.version }}
请保持简洁,使用纯文本格式,不要使用Markdown语法,使用emoji表情符号增加可读性。
重要:除了下载链接外,不要包含任何其他链接。如果更新日志中包含其他链接,请将它们移除。`
}
]
})
});
const data = await response.json();
const message = data.choices[0].message.content.trim();
core.setOutput('message', message);
console.log('Generated Chinese message');
} catch (error) {
console.error('Error calling OpenRouter API:', error.message);
const defaultMessage = `🚀 Blinko ${{ needs.set-version.outputs.version }} 已发布!\n\n📝 更新日志:\n${{ needs.generate-changelog.outputs.changelog }}\n\n📥 下载链接:\nhttps://github.com/${{ github.repository }}/releases/tag/${{ needs.set-version.outputs.version }}`;
core.setOutput('message', defaultMessage);
}
- name: Generate English message using OpenRouter AI
id: generate_english
uses: actions/github-script@v7
with:
script: |
try {
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer ${{ secrets.OPENROUTER_API_KEY }}',
'Content-Type': 'application/json'
},
body: JSON.stringify({
model: 'qwen/qwen-2.5-72b-instruct',
messages: [
{
role: 'user',
content: `Format the following release notification as a plain text Telegram message (no Markdown):
Version: ${{ needs.set-version.outputs.version }}
Changelog:
${{ needs.generate-changelog.outputs.changelog }}
Download: https://github.com/${{ github.repository }}/releases/tag/${{ needs.set-version.outputs.version }}
Keep it concise, use plain text format, no Markdown syntax, and use emoji for better readability.
IMPORTANT: Only include the download link, remove all other links. If the changelog contains other links, remove them.`
}
]
})
});
const data = await response.json();
const message = data.choices[0].message.content.trim();
core.setOutput('message', message);
console.log('Generated English message');
} catch (error) {
console.error('Error calling OpenRouter API:', error.message);
const defaultMessage = `🚀 Blinko ${{ needs.set-version.outputs.version }} has been released!\n\n📝 Changelog:\n${{ needs.generate-changelog.outputs.changelog }}\n\n📥 Download:\nhttps://github.com/${{ github.repository }}/releases/tag/${{ needs.set-version.outputs.version }}`;
core.setOutput('message', defaultMessage);
}
# Send notification to Telegram groups
notify-telegram:
runs-on: ubuntu-latest
needs: [set-version, update-release, generate-changelog, process-notification]
steps:
- name: Send notification to Telegram group 1 (Chinese)
uses: appleboy/telegram-action@v0.1.1
continue-on-error: true
with:
to: ${{ secrets.TELEGRAM_GROUP_ID_1 }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
format: html
debug: true
message: |
${{ needs.process-notification.outputs.chinese_message }}
- name: Send notification to Telegram group 2 (English)
uses: appleboy/telegram-action@v0.1.1
continue-on-error: true
with:
to: ${{ secrets.TELEGRAM_GROUP_ID_2 }}
token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
format: html
debug: true
message: |
${{ needs.process-notification.outputs.english_message }}