Skip to content

Release (build all + publish) #13

Release (build all + publish)

Release (build all + publish) #13

Workflow file for this run

name: Release (build all + publish)
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: write
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
jobs:
build-android:
runs-on: ubuntu-latest
outputs:
release_base: ${{ steps.vars.outputs.release_base }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'
- name: Install Android command-line tools and SDK components (API 29)
run: |
sudo apt-get update
sudo apt-get install -y unzip wget
ANDROID_SDK_ROOT=$HOME/Android/Sdk
mkdir -p $ANDROID_SDK_ROOT
wget -q https://dl.google.com/android/repository/commandlinetools-linux-9477386_latest.zip -O /tmp/cmdline-tools.zip
unzip -q /tmp/cmdline-tools.zip -d /tmp/cmdline-tools
mkdir -p $ANDROID_SDK_ROOT/cmdline-tools/latest
mv /tmp/cmdline-tools/cmdline-tools/* $ANDROID_SDK_ROOT/cmdline-tools/latest/
echo "ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT" >> $GITHUB_ENV
echo "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin" >> $GITHUB_PATH
echo "$ANDROID_SDK_ROOT/platform-tools" >> $GITHUB_PATH
export PATH="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$PATH"
yes | sdkmanager --sdk_root=$ANDROID_SDK_ROOT --licenses || true
sdkmanager --sdk_root=$ANDROID_SDK_ROOT "platform-tools" "platforms;android-29" "build-tools;29.0.3"
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
- name: Cache pub and Gradle
uses: actions/cache@v4
with:
path: |
~/.pub-cache
~/.gradle/caches
key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.yaml') }}-${{ hashFiles('**/gradle-wrapper.properties') }}
- name: Flutter pub get
run: flutter pub get
- name: Accept Android SDK licenses
run: |
yes | sdkmanager --licenses || true
- name: Build Android AAB, fetch/install core, and package
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
flutter pub run tools/fetch_core_local.dart --repo sipeed/picoclaw --tag latest --out-dir app/bin --platform android --arch arm64 --build-mode release --install-to-build
- name: Build Android APK (debug) and fetch/install core
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
flutter pub run tools/fetch_core_local.dart --repo sipeed/picoclaw --tag latest --out-dir app/bin --platform android --arch arm64 --build-mode debug --install-to-build
- name: Prepare release metadata
id: vars
run: |
now=$(date -u +%y%m%d)
short=$(git rev-parse --short=6 $GITHUB_SHA)
base_no_prefix="$now-$short"
release_tag="picoclaw_fui-$base_no_prefix"
echo "release_base=$base_no_prefix" >> $GITHUB_OUTPUT
echo "RELEASE_BASE=$base_no_prefix" >> $GITHUB_ENV
echo "RELEASE_TAG=$release_tag" >> $GITHUB_ENV
- name: Collect and rename Android artifacts
run: |
set -e
PKG_NAME=picoclaw_fui
TAG=${RELEASE_BASE}
AAB_NAME=${PKG_NAME}-${TAG}-android-arm_arm64.aab
APK_NAME=${PKG_NAME}-${TAG}-android-universal.apk
rm -f "$AAB_NAME" "$APK_NAME" || true
if ls build/app/outputs/bundle/release/*.aab 1> /dev/null 2>&1; then
cp build/app/outputs/bundle/release/*.aab "$AAB_NAME"
else
echo "AAB not found"; exit 1
fi
if [ -f build/app/outputs/flutter-apk/app-debug.apk ]; then
cp build/app/outputs/flutter-apk/app-debug.apk "$APK_NAME"
else
echo "Debug APK not found"; exit 1
fi
# core binaries are installed into build outputs; avoid uploading app/bin
- name: Upload AAB artifact
uses: actions/upload-artifact@v4
with:
name: picoclaw_fui-${{ env.RELEASE_BASE }}-android-arm_arm64.aab
path: picoclaw_fui-${{ env.RELEASE_BASE }}-android-arm_arm64.aab
- name: Upload APK artifact
uses: actions/upload-artifact@v4
with:
name: picoclaw_fui-${{ env.RELEASE_BASE }}-android-universal.apk
path: picoclaw_fui-${{ env.RELEASE_BASE }}-android-universal.apk
build-macos:
runs-on: macos-latest
needs: []
outputs:
release_base: ${{ steps.vars.outputs.release_base }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
- name: Flutter pub get
run: flutter pub get
- name: Build macOS release (build + fetch/install core)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
flutter pub run tools/fetch_core_local.dart --repo sipeed/picoclaw --tag latest --out-dir app/bin --platform macos --arch arm64 --build-mode release --install-to-build
- name: Prepare release metadata
id: vars
run: |
now=$(date -u +%y%m%d)
short=$(git rev-parse --short=6 $GITHUB_SHA)
base_no_prefix="$now-$short"
release_tag="picoclaw_fui-$base_no_prefix"
echo "release_base=$base_no_prefix" >> $GITHUB_OUTPUT
echo "RELEASE_BASE=$base_no_prefix" >> $GITHUB_ENV
echo "RELEASE_TAG=$release_tag" >> $GITHUB_ENV
- name: Package Release (dmg)
run: |
dest="picoclaw_fui-${RELEASE_BASE}-macos-arm64.dmg"
rm -f "$dest" || true
out_dir="build/macos/Build/Products/Release"
if [ ! -d "$out_dir" ]; then
echo "Release output not found"; exit 1
fi
app_path=$(find "$out_dir" -maxdepth 1 -name "*.app" -print -quit)
if [ -z "$app_path" ]; then
echo "No .app found in $out_dir"; ls -la "$out_dir" || true; exit 1
fi
stage_dir=$(mktemp -d)
cp -R "$app_path" "$stage_dir/"
hdiutil create -volname "PicoClawFUI" -srcfolder "$stage_dir" -ov -format UDZO "$dest"
- name: Upload macOS DMG artifact
uses: actions/upload-artifact@v4
with:
name: picoclaw_fui-${{ env.RELEASE_BASE }}-macos-arm64.dmg
path: picoclaw_fui-${{ env.RELEASE_BASE }}-macos-arm64.dmg
build-windows:
runs-on: windows-latest
needs: []
outputs:
release_base: ${{ steps.vars.outputs.release_base }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
- name: Flutter pub get
run: flutter pub get
- name: Locate MSBuild and add to PATH
shell: powershell
run: |
Write-Output "Locating MSBuild with vswhere and adding to PATH"
$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe'
if (-not (Test-Path $vswhere)) {
Write-Error "vswhere not found at $vswhere"
exit 1
}
$inst = & $vswhere -latest -requires Microsoft.Component.MSBuild -products * -property installationPath
if (-not $inst) {
Write-Error "Visual Studio with MSBuild not found"
exit 1
}
$msbuildDir = Join-Path $inst 'MSBuild\Current\Bin'
Write-Output "Found MSBuild dir: $msbuildDir"
Add-Content -Path $env:GITHUB_PATH -Value $msbuildDir
- name: Verify VS toolchain
shell: powershell
run: |
Write-Output "--- Verify MSVC / MSBuild / NuGet ---"
msbuild -version
if (Get-Command cl.exe -ErrorAction SilentlyContinue) { cl.exe /? } else { Write-Output 'cl.exe not found' }
if (-not (Get-Command nuget -ErrorAction SilentlyContinue)) { choco install nuget.commandline -y }
nuget help
- name: Build Windows release (build + fetch/install core)
shell: powershell
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
flutter pub run tools/fetch_core_local.dart --repo sipeed/picoclaw --tag latest --out-dir app/bin --platform windows --arch x86_64 --build-mode release --install-to-build
- name: Prepare release metadata
id: vars
shell: powershell
run: |
$date = Get-Date -Format 'yyMMdd'
$short = git rev-parse --short=6 $env:GITHUB_SHA
$base_no_prefix = "$date-$short"
$release_tag = "picoclaw_fui-$base_no_prefix"
Add-Content -Path $env:GITHUB_OUTPUT -Value "release_base=$base_no_prefix"
Add-Content -Path $env:GITHUB_ENV -Value "RELEASE_BASE=$base_no_prefix"
Add-Content -Path $env:GITHUB_ENV -Value "RELEASE_TAG=$release_tag"
- name: Zip Release
shell: powershell
run: |
$dest = "picoclaw_fui-${env:RELEASE_BASE}-windows-x64.zip"
Compress-Archive -Path 'build\\windows\\x64\\runner\\Release\\*' -DestinationPath $dest -Force
# core binaries are installed into build outputs; avoid uploading app/bin
- name: Upload Windows ZIP artifact
uses: actions/upload-artifact@v4
with:
name: picoclaw_fui-${{ env.RELEASE_BASE }}-windows-x64.zip
path: picoclaw_fui-${{ env.RELEASE_BASE }}-windows-x64.zip
build-linux:
runs-on: ubuntu-22.04
outputs:
release_base: ${{ steps.vars.outputs.release_base }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
- name: Install Linux build dependencies
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
clang cmake ninja-build pkg-config pkgconf build-essential \
libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev \
lld binutils libstdc++-12-dev libglu1-mesa
- name: Cache pub
uses: actions/cache@v4
with:
path: |
~/.pub-cache
key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.yaml') }}
- name: Flutter pub get
run: flutter pub get
- name: Fetch core and build Linux release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
flutter pub run tools/fetch_core_local.dart --repo sipeed/picoclaw --tag latest --out-dir app/bin --platform linux --arch x64 --build-mode release --install-to-build || true
flutter build linux --release
- name: Prepare release metadata
id: vars
run: |
now=$(date -u +%y%m%d)
short=$(git rev-parse --short=6 $GITHUB_SHA)
base_no_prefix="$now-$short"
release_tag="picoclaw_fui-$base_no_prefix"
echo "release_base=$base_no_prefix" >> $GITHUB_OUTPUT
echo "RELEASE_BASE=$base_no_prefix" >> $GITHUB_ENV
echo "RELEASE_TAG=$release_tag" >> $GITHUB_ENV
- name: Package Linux as .deb
run: |
set -e
PKG_NAME=picoclaw_fui
TAG=${RELEASE_BASE}
DEST=${PKG_NAME}-${TAG}-linux-x64.deb
PKGROOT=$PWD/pkg_root
rm -rf "$PKGROOT" "$DEST"
BUNDLE_DIR=build/linux/x64/release/bundle
if [ ! -d "$BUNDLE_DIR" ]; then echo "Bundle not found: $BUNDLE_DIR"; ls -la build/linux || true; exit 1; fi
mkdir -p "$PKGROOT/opt/${PKG_NAME}/${TAG}"
cp -r "$BUNDLE_DIR"/* "$PKGROOT/opt/${PKG_NAME}/${TAG}/"
mkdir -p "$PKGROOT/usr/bin"
printf '%s\n' \
'#!/bin/sh' \
'set -e' \
'BASE=/opt/picoclaw_fui' \
'if [ -d "$BASE" ]; then' \
' DIRNAME=$(ls -1 "$BASE" 2>/dev/null | sort -V | tail -n1)' \
' if [ -n "$DIRNAME" ] && [ -d "$BASE/$DIRNAME" ]; then' \
' DIR="$BASE/$DIRNAME"' \
' else' \
' DIR="$BASE"' \
' fi' \
'else' \
' DIR="$BASE"' \
'fi' \
'EXEC=$(find "$DIR" -maxdepth 1 -type f -executable -print -quit)' \
'if [ -z "$EXEC" ]; then' \
' echo "Executable not found in $DIR" >&2' \
' exit 1' \
'fi' \
'exec "$EXEC" "$@"' > "$PKGROOT/usr/bin/${PKG_NAME}"
chmod 0755 "$PKGROOT/usr/bin/${PKG_NAME}"
mkdir -p "$PKGROOT/DEBIAN"
# Install icon and desktop entry
mkdir -p "$PKGROOT/usr/share/icons/hicolor/128x128/apps"
mkdir -p "$PKGROOT/usr/share/applications"
if [ -f assets/app_icon.png ]; then
cp assets/app_icon.png "$PKGROOT/usr/share/icons/hicolor/128x128/apps/picoclaw_fui.png"
fi
printf '%s\n' \
"[Desktop Entry]" \
"Name=PicoClaw FUI" \
"Exec=/usr/bin/picoclaw_fui %U" \
"Icon=picoclaw_fui" \
"Type=Application" \
"Categories=Utility;" \
"Terminal=false" > "$PKGROOT/usr/share/applications/picoclaw_fui.desktop"
printf '%s\n' \
"Package: picoclaw-fui" \
"Version: ${TAG}" \
"Section: utils" \
"Priority: optional" \
"Architecture: amd64" \
"Maintainer: GitHub Actions <actions@github.com>" \
"Description: PicoClaw FUI" > "$PKGROOT/DEBIAN/control"
# Update icon cache if available (ignore errors)
if command -v gtk-update-icon-cache >/dev/null 2>&1; then
gtk-update-icon-cache -f "$PKGROOT/usr/share/icons/hicolor" || true
fi
dpkg-deb --build "$PKGROOT" "$DEST"
- name: Upload Linux .deb artifact
uses: actions/upload-artifact@v4
with:
name: picoclaw_fui-${{ env.RELEASE_BASE }}-linux-x64.deb
path: picoclaw_fui-${{ env.RELEASE_BASE }}-linux-x64.deb
publish:
needs: [build-android, build-windows, build-macos, build-linux]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: downloaded_artifacts
- name: List downloaded files
run: ls -la downloaded_artifacts || true
- name: Move downloaded artifacts to workspace root
run: |
shopt -s globstar || true
find downloaded_artifacts -type f -exec mv -t . {} + || true
- name: Set release vars from build outputs
run: echo "RELEASE_BASE=${{ needs.build-android.outputs.release_base }}" >> $GITHUB_ENV
- name: Publish Release and upload artifacts
uses: ncipollo/release-action@v1
with:
tag: picoclaw_fui-${{ env.RELEASE_BASE }}
name: picoclaw_fui-${{ env.RELEASE_BASE }}
allowUpdates: true
artifacts: |
picoclaw_fui-${{ env.RELEASE_BASE }}-android-arm_arm64.aab
picoclaw_fui-${{ env.RELEASE_BASE }}-android-universal.apk
picoclaw_fui-${{ env.RELEASE_BASE }}-windows-x64.zip
picoclaw_fui-${{ env.RELEASE_BASE }}-macos-arm64.dmg
picoclaw_fui-${{ env.RELEASE_BASE }}-linux-x64.deb
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}