Skip to content

Update CI: test build.sh deployment script instead of separate aceste… #3

Update CI: test build.sh deployment script instead of separate aceste…

Update CI: test build.sh deployment script instead of separate aceste… #3

Workflow file for this run

name: Release
on:
release:
workflow_dispatch:
inputs:
tag:
description: "Release tag (e.g. v1.0.0)"
required: true
default: "v0.0.0-dev"
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: true
env:
ACESTEP_CPP_REPO: https://github.com/audiohacking/acestep.cpp.git
NODE_VERSION: "20"
jobs:
# ────────────────────────────────────────────────────────────────────────────
# 1. Build the React frontend (platform-independent)
# ────────────────────────────────────────────────────────────────────────────
build-frontend:
name: Build frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
- name: Install & build
run: npm ci && npm run build
- uses: actions/upload-artifact@v4
with:
name: frontend-dist
path: dist/
retention-days: 1
# ────────────────────────────────────────────────────────────────────────────
# 2. Compile the Node.js server (platform-independent JS)
# ────────────────────────────────────────────────────────────────────────────
build-server:
name: Build Node.js server
runs-on: ubuntu-latest
defaults:
run:
working-directory: server
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: server/package-lock.json
- name: Install, compile & prune to production deps
run: |
npm ci
npm run build
npm prune --production
- uses: actions/upload-artifact@v4
with:
name: server-bundle
path: |
server/dist/
server/node_modules/
server/package.json
retention-days: 1
# ────────────────────────────────────────────────────────────────────────────
# 3. Per-platform: assemble the bundle with build + model scripts
# acestep.cpp is NOT compiled here — it is compiled on the user's machine
# by build.sh / build.bat on first launch, which detects the actual GPU.
# ────────────────────────────────────────────────────────────────────────────
build-platform:
name: Bundle ${{ matrix.label }}
needs: [build-frontend, build-server]
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- label: linux-x64
os: linux
- label: linux-arm64
os: linux
- label: macos-arm64
os: macos
- label: windows-x64
os: windows
steps:
- uses: actions/checkout@v4
# ── Download pre-built UI artifacts ─────────────────────────────────
- uses: actions/download-artifact@v4
with:
name: frontend-dist
path: _release/dist
- uses: actions/download-artifact@v4
with:
name: server-bundle
path: _release/server-bundle
# ── Assemble the release bundle ──────────────────────────────────────
- name: Assemble bundle
shell: bash
run: |
set -e
APP=acestep-cpp-ui
mkdir -p "$APP/bin" "$APP/dist" "$APP/server/dist" "$APP/server/node_modules" \
"$APP/data" "$APP/public/audio" "$APP/logs" "$APP/models"
# Node.js server (compiled JS + production node_modules)
cp -r _release/server-bundle/dist/. "$APP/server/dist/"
cp -r _release/server-bundle/node_modules/. "$APP/server/node_modules/"
cp _release/server-bundle/package.json "$APP/server/"
# React frontend (served by the API server)
cp -r _release/dist/. "$APP/dist/"
# .env template
cp .env.example "$APP/.env.example"
# Build scripts — compile acestep.cpp with GPU detection on first run
cp build.sh "$APP/build.sh"
chmod +x "$APP/build.sh"
cp build.bat "$APP/build.bat"
# Model download scripts
cp models.sh "$APP/models.sh"
chmod +x "$APP/models.sh"
cp models.bat "$APP/models.bat"
# ── start.sh (Linux / macOS) ──────────────────────────────────────
cat > "$APP/start.sh" << 'SH'
#!/bin/bash
# ACE-Step UI — start
# On first launch: compiles acestep.cpp for your GPU and downloads base models.
set -e

Check failure on line 150 in .github/workflows/release.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/release.yml

Invalid workflow file

You have an error in your yaml syntax on line 150
DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$DIR"
# Load .env if present
[ -f .env ] && export $(grep -v '^#' .env | grep -v '^\s*$' | xargs)
# ── First-run: compile acestep.cpp ───────────────────────────────────────────
if [ ! -x "$DIR/bin/ace-qwen3" ] || [ ! -x "$DIR/bin/dit-vae" ]; then
echo "═══════════════════════════════════════════════════════"
echo " First run: building acestep.cpp for your hardware"
echo " GPU support (CUDA / ROCm / Vulkan / Metal) is"
echo " detected automatically from your system."
echo " This takes a few minutes and only happens once."
echo "═══════════════════════════════════════════════════════"
echo ""
bash "$DIR/build.sh"
echo ""
fi
# ── First-run: download models ───────────────────────────────────────────────
: "${MODELS_DIR:=$DIR/models}"
if ! ls "$MODELS_DIR"/*.gguf &>/dev/null 2>&1; then
echo "═══════════════════════════════════════════════════════"
echo " First run: downloading base GGUF models (~8 GB)"
echo " VAE + Text Encoder + LM-4B + DiT-Turbo (Q8_0)"
echo " Requires: curl or wget"
echo "═══════════════════════════════════════════════════════"
echo ""
bash "$DIR/models.sh" --dir "$MODELS_DIR"
echo ""
fi
# ── Start the server ─────────────────────────────────────────────────────────
: "${ACE_QWEN3_BIN:=$DIR/bin/ace-qwen3}"
: "${DIT_VAE_BIN:=$DIR/bin/dit-vae}"
: "${PORT:=3001}"
mkdir -p logs data public/audio
echo "Starting ACE-Step UI on port $PORT ..."
ACE_QWEN3_BIN="$ACE_QWEN3_BIN" \
DIT_VAE_BIN="$DIT_VAE_BIN" \
MODELS_DIR="$MODELS_DIR" \
PORT="$PORT" \
DATABASE_PATH="$DIR/data/acestep.db" \
AUDIO_DIR="$DIR/public/audio" \
FRONTEND_URL="http://localhost:$PORT" \
node "$DIR/server/dist/index.js" &
NODE_PID=$!
sleep 2
echo ""
echo "ACE-Step UI → http://localhost:$PORT"
echo ""
trap 'kill $NODE_PID 2>/dev/null; exit 0' INT TERM
wait $NODE_PID
SH
chmod +x "$APP/start.sh"
# ── start.bat (Windows) ───────────────────────────────────────────
cat > "$APP/start.bat" << 'BAT'
@echo off
:: ACE-Step UI — start
:: On first launch: compiles acestep.cpp for your GPU and downloads base models.
setlocal EnableDelayedExpansion
set DIR=%~dp0
cd /d "%DIR%"
:: Load .env if present
if exist ".env" (
for /f "usebackq tokens=* delims=" %%l in (".env") do (
set line=%%l
if not "!line:~0,1!"=="#" if not "!line!"=="" set %%l
)
)
:: First-run: compile acestep.cpp
if not exist "%DIR%bin\ace-qwen3.exe" (
echo ═══════════════════════════════════════════════════════
echo First run: building acestep.cpp for your hardware
echo GPU support ^(CUDA / Vulkan^) is detected automatically.
echo This takes a few minutes and only happens once.
echo ═══════════════════════════════════════════════════════
echo.
call "%DIR%build.bat"
if %ERRORLEVEL% NEQ 0 ( echo Build failed. See output above. & pause & exit /b 1 )
echo.
)
:: First-run: download models
if "%MODELS_DIR%"=="" set MODELS_DIR=%DIR%models
dir /b "%MODELS_DIR%\*.gguf" >nul 2>&1
if %ERRORLEVEL% NEQ 0 (
echo ═══════════════════════════════════════════════════════
echo First run: downloading base GGUF models ~8 GB
echo VAE + Text Encoder + LM-4B + DiT-Turbo ^(Q8_0^)
echo ═══════════════════════════════════════════════════════
echo.
call "%DIR%models.bat" --dir "%MODELS_DIR%"
echo.
)
:: Start the server
if "%ACE_QWEN3_BIN%"=="" set ACE_QWEN3_BIN=%DIR%bin\ace-qwen3.exe
if "%DIT_VAE_BIN%"=="" set DIT_VAE_BIN=%DIR%bin\dit-vae.exe
if "%PORT%"=="" set PORT=3001
mkdir logs 2>nul & mkdir data 2>nul & mkdir public\audio 2>nul
echo Starting ACE-Step UI on port %PORT% ...
set DATABASE_PATH=%DIR%data\acestep.db
set AUDIO_DIR=%DIR%public\audio
set FRONTEND_URL=http://localhost:%PORT%
node "%DIR%server\dist\index.js"
BAT
# ── Release README ────────────────────────────────────────────────
cat > "$APP/README.md" << 'MD'
# ACE-Step UI
Self-contained release bundle — no Python required.
Music generation is powered by [acestep.cpp](https://github.com/audiohacking/acestep.cpp).
## Requirements
- **Node.js ≥ 20** — runtime for the API server ([nodejs.org](https://nodejs.org))
- **cmake + git** — required by `build.sh` / `build.bat` to compile `acestep.cpp`
- **curl or wget** — required by `models.sh` to download model files
- **~8 GB free disk space** — for the default `Q8_0` model set
## Quick Start
```bash
# Just run start.sh — it handles everything on first launch:
# 1. Detects your GPU (CUDA / ROCm / Vulkan / Metal) and compiles acestep.cpp
# 2. Downloads the base GGUF models (~8 GB)
# 3. Starts the UI on http://localhost:3001
./start.sh
```
On Windows:
```bat
start.bat
```
## GPU Acceleration
`build.sh` / `build.bat` automatically detect your GPU on first launch:
| GPU | Flag used |
|-----|-----------|
| NVIDIA (CUDA) | `-DGGML_CUDA=ON` |
| AMD (ROCm/HIP) | `-DGGML_HIP=ON` |
| Any (Vulkan) | `-DGGML_VULKAN=ON` |
| macOS (Metal) | auto-detected by cmake |
| CPU only | no flags |
To force a specific backend, run the build script manually:
```bash
./build.sh --cuda # Force CUDA
./build.sh --rocm # Force ROCm/HIP
./build.sh --vulkan # Force Vulkan
./build.sh --cpu # CPU-only
```
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `ACE_QWEN3_BIN` | `./bin/ace-qwen3` | Path to the ace-qwen3 LLM binary |
| `DIT_VAE_BIN` | `./bin/dit-vae` | Path to the dit-vae binary |
| `MODELS_DIR` | `./models` | Directory containing GGUF model files |
| `PORT` | `3001` | API + UI server port |
| `AUDIO_DIR` | `./public/audio` | Where generated audio is stored |
| `JWT_SECRET` | built-in | Change for multi-user deployments |
Copy `.env.example` → `.env` to customise these.
## Model Management
Download models manually (useful for selecting a different quantisation):
```bash
./models.sh # Default: Q8_0 essentials (~8 GB)
./models.sh --quant Q5_K_M # Smaller, slightly lower quality
./models.sh --all # Every model and quantisation
```
MD
echo "Bundle assembled for ${{ matrix.label }}:"
ls -lh "$APP/"
# ── Package ──────────────────────────────────────────────────────────
- name: Create archive (tar.gz)
if: matrix.os != 'windows'
shell: bash
run: |
TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}"
[[ "$TAG" != v* ]] && TAG="${{ github.event.inputs.tag || 'v0.0.0-dev' }}"
ARCHIVE="acestep-cpp-ui-${TAG}-${{ matrix.label }}.tar.gz"
tar -czf "$ARCHIVE" acestep-cpp-ui/
echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV"
ls -lh "$ARCHIVE"
- name: Create archive (zip — Windows)
if: matrix.os == 'windows'
shell: bash
run: |
TAG="${GITHUB_REF_NAME:-${{ github.event.inputs.tag }}}"
[[ "$TAG" != v* ]] && TAG="${{ github.event.inputs.tag || 'v0.0.0-dev' }}"
ARCHIVE="acestep-cpp-ui-${TAG}-${{ matrix.label }}.zip"
zip -qr "$ARCHIVE" acestep-cpp-ui/
echo "ARCHIVE=$ARCHIVE" >> "$GITHUB_ENV"
ls -lh "$ARCHIVE"
- uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.label }}
path: ${{ env.ARCHIVE }}
retention-days: 7
# ────────────────────────────────────────────────────────────────────────────
# 4. Publish GitHub Release
# ────────────────────────────────────────────────────────────────────────────
publish-release:
name: Publish GitHub Release
needs: build-platform
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/download-artifact@v4
with:
pattern: release-*
path: release-artifacts
merge-multiple: true
- name: List artifacts
run: ls -lh release-artifacts/
- name: Resolve tag
id: tag
run: |
TAG="${GITHUB_REF_NAME:-}"
[[ "$TAG" == v* ]] || TAG="${{ github.event.inputs.tag || 'v0.0.0-dev' }}"
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
- name: Generate changelog
id: changelog
run: |
PREV=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
if [ -n "$PREV" ]; then
LOG=$(git log "${PREV}..HEAD" --oneline --no-decorate 2>/dev/null | head -50)
else
LOG=$(git log --oneline --no-decorate | head -30)
fi
{ echo "log<<EOF"; echo "$LOG"; echo "EOF"; } >> "$GITHUB_OUTPUT"
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.tag.outputs.tag }}
name: "ACE-Step UI ${{ steps.tag.outputs.tag }}"
draft: false
prerelease: ${{ contains(steps.tag.outputs.tag, '-') }}
body: |
## ACE-Step UI ${{ steps.tag.outputs.tag }}
Self-contained bundle — **no Python required**.
Music generation is powered by [acestep.cpp](https://github.com/audiohacking/acestep.cpp).
> **GPU acceleration is built on your machine** — `start.sh` / `start.bat` automatically
> detects your GPU (CUDA / ROCm / Vulkan / Metal) and compiles `acestep.cpp` on first launch.
> Models are also downloaded automatically on first run.
### Platforms
| File | OS | Arch |
|------|----|------|
| `*-linux-x64.tar.gz` | Linux | x86\_64 |
| `*-linux-arm64.tar.gz` | Linux | ARM64 |
| `*-macos-arm64.tar.gz` | macOS | Apple Silicon |
| `*-windows-x64.zip` | Windows | x86\_64 |
### Requirements
- **Node.js ≥ 20** — [nodejs.org](https://nodejs.org)
- **cmake + git** — to compile `acestep.cpp` on first launch
- **curl or wget** — to download GGUF model files on first launch
### Quick Start
```bash
tar xzf acestep-cpp-ui-*-linux-x64.tar.gz
cd acestep-cpp-ui
./start.sh # builds acestep.cpp, downloads models, starts UI → http://localhost:3001
```
On Windows: extract the `.zip` and run `start.bat`.
### What's Changed
${{ steps.changelog.outputs.log }}
files: release-artifacts/*
fail_on_unmatched_files: false