Skip to content

Merge pull request #14 from 0xtbug/dev #21

Merge pull request #14 from 0xtbug/dev

Merge pull request #14 from 0xtbug/dev #21

Workflow file for this run

name: Build and Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Version to release (e.g., 1.1.0)'
required: true
type: string
permissions:
contents: write
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
jobs:
# ===========================================
# 1. Create Release + Version Bump
# ===========================================
create-release:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
release_id: ${{ steps.create_release.outputs.id }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get version
id: get_version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ github.event.inputs.version }}"
else
VERSION="${GITHUB_REF#refs/tags/v}"
fi
VERSION="${VERSION#v}"
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Releasing version: $VERSION"
- name: Bump version in project files
run: |
chmod +x ./scripts/bump-version.sh
./scripts/bump-version.sh "${{ steps.get_version.outputs.version }}"
- name: Commit version bump
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
if git diff --quiet package.json src-tauri/tauri.conf.json src-tauri/Cargo.toml; then
echo "No version changes to commit"
else
git add package.json src-tauri/tauri.conf.json src-tauri/Cargo.toml
git commit -m "chore: bump version to ${{ steps.get_version.outputs.version }} [skip ci]"
git push origin HEAD:main
fi
- name: Create tag (for workflow_dispatch)
if: github.event_name == 'workflow_dispatch'
run: |
TAG_NAME="v${{ steps.get_version.outputs.version }}"
if ! git tag -l | grep -q "^${TAG_NAME}$"; then
git tag -a "${TAG_NAME}" -m "Release ${{ steps.get_version.outputs.version }}"
git push origin "${TAG_NAME}"
fi
- name: Create draft release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ steps.get_version.outputs.version }}
name: ZeroLimit v${{ steps.get_version.outputs.version }}
draft: true
generate_release_notes: true
body: |
> ⚠️ **Note**: macOS builds won't be code-signed unless you add Apple signing secrets. Unsigned macOS apps require users to run:
> ```bash
> xattr -cr /Applications/ZeroLimit.app
> ```
# ===========================================
# 2. Build Windows x64
# ===========================================
build-windows-x64:
needs: create-release
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
src-tauri/target/
key: ${{ runner.os }}-cargo-x64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-x64-
- name: Install frontend dependencies
run: pnpm install
- name: Build Tauri (x64)
run: pnpm tauri build --target x86_64-pc-windows-msvc
- name: Rename and Prepare artifacts
shell: bash
run: |
VERSION="${{ needs.create-release.outputs.version }}"
# Portable EXE
cp src-tauri/target/x86_64-pc-windows-msvc/release/zero-limit.exe "ZeroLimit_${VERSION}_Windows_x64_portable.exe"
# NSIS Installer
mv src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/ZeroLimit_${VERSION}_x64-setup.exe "ZeroLimit_${VERSION}_Windows_x64-setup.exe"
mv src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/ZeroLimit_${VERSION}_x64-setup.exe.sig "ZeroLimit_${VERSION}_Windows_x64-setup.exe.sig"
# MSI Installer
mv src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/ZeroLimit_${VERSION}_x64_en-US.msi "ZeroLimit_${VERSION}_Windows_x64.msi"
mv src-tauri/target/x86_64-pc-windows-msvc/release/bundle/msi/ZeroLimit_${VERSION}_x64_en-US.msi.sig "ZeroLimit_${VERSION}_Windows_x64.msi.sig"
- name: Upload artifacts to release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: true
files: |
ZeroLimit_*_Windows_x64-setup.exe
ZeroLimit_*_Windows_x64-setup.exe.sig
ZeroLimit_*_Windows_x64.msi
ZeroLimit_*_Windows_x64.msi.sig
ZeroLimit_*_Windows_x64_portable.exe
- name: Upload signatures for latest.json
uses: actions/upload-artifact@v4
with:
name: signatures-windows-x64
path: ZeroLimit_*_Windows_x64-setup.exe.sig
# ===========================================
# 3. Build Windows ARM64
# ===========================================
build-windows-arm64:
needs: create-release
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-pc-windows-msvc
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
src-tauri/target/
key: ${{ runner.os }}-cargo-arm64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-arm64-
- name: Install frontend dependencies
run: pnpm install
- name: Build Tauri (ARM64)
run: pnpm tauri build --target aarch64-pc-windows-msvc
- name: Rename and Prepare artifacts
shell: bash
run: |
VERSION="${{ needs.create-release.outputs.version }}"
# Portable EXE
cp src-tauri/target/aarch64-pc-windows-msvc/release/zero-limit.exe "ZeroLimit_${VERSION}_Windows_arm64_portable.exe"
# NSIS Installer
mv src-tauri/target/aarch64-pc-windows-msvc/release/bundle/nsis/ZeroLimit_${VERSION}_arm64-setup.exe "ZeroLimit_${VERSION}_Windows_arm64-setup.exe"
mv src-tauri/target/aarch64-pc-windows-msvc/release/bundle/nsis/ZeroLimit_${VERSION}_arm64-setup.exe.sig "ZeroLimit_${VERSION}_Windows_arm64-setup.exe.sig"
# MSI Installer
mv src-tauri/target/aarch64-pc-windows-msvc/release/bundle/msi/ZeroLimit_${VERSION}_arm64_en-US.msi "ZeroLimit_${VERSION}_Windows_arm64.msi"
mv src-tauri/target/aarch64-pc-windows-msvc/release/bundle/msi/ZeroLimit_${VERSION}_arm64_en-US.msi.sig "ZeroLimit_${VERSION}_Windows_arm64.msi.sig"
- name: Upload artifacts to release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: true
files: |
ZeroLimit_*_Windows_arm64-setup.exe
ZeroLimit_*_Windows_arm64-setup.exe.sig
ZeroLimit_*_Windows_arm64.msi
ZeroLimit_*_Windows_arm64.msi.sig
ZeroLimit_*_Windows_arm64_portable.exe
- name: Upload signatures for latest.json
uses: actions/upload-artifact@v4
with:
name: signatures-windows-arm64
path: ZeroLimit_*_Windows_arm64-setup.exe.sig
# ===========================================
# 4. Build macOS Intel (x64)
# ===========================================
build-macos-x64:
needs: create-release
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-apple-darwin
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
src-tauri/target/
key: ${{ runner.os }}-cargo-x64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-x64-
- name: Install frontend dependencies
run: pnpm install
- name: Build Tauri (Intel)
run: pnpm tauri build --target x86_64-apple-darwin
- name: Rename and Prepare artifacts
run: |
VERSION="${{ needs.create-release.outputs.version }}"
# Rename Intel artifacts
mv src-tauri/target/x86_64-apple-darwin/release/bundle/dmg/ZeroLimit_${VERSION}_x64.dmg "ZeroLimit_${VERSION}_macOS_x64.dmg"
mv src-tauri/target/x86_64-apple-darwin/release/bundle/macos/ZeroLimit.app.tar.gz "ZeroLimit_${VERSION}_macOS_x64.app.tar.gz"
mv src-tauri/target/x86_64-apple-darwin/release/bundle/macos/ZeroLimit.app.tar.gz.sig "ZeroLimit_${VERSION}_macOS_x64.app.tar.gz.sig"
- name: Upload artifacts to release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: true
files: |
ZeroLimit_*_macOS_x64.dmg
ZeroLimit_*_macOS_x64.app.tar.gz
ZeroLimit_*_macOS_x64.app.tar.gz.sig
- name: Upload signatures for latest.json
uses: actions/upload-artifact@v4
with:
name: signatures-macos-x64
path: ZeroLimit_*_macOS_x64.app.tar.gz.sig
# ===========================================
# 5. Build macOS Apple Silicon (ARM64)
# ===========================================
build-macos-arm64:
needs: create-release
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-apple-darwin
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
src-tauri/target/
key: ${{ runner.os }}-cargo-arm64-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-arm64-
- name: Install frontend dependencies
run: pnpm install
- name: Build Tauri (Apple Silicon)
run: pnpm tauri build --target aarch64-apple-darwin
- name: Rename and Prepare artifacts
run: |
VERSION="${{ needs.create-release.outputs.version }}"
# Rename Apple Silicon artifacts
mv src-tauri/target/aarch64-apple-darwin/release/bundle/dmg/ZeroLimit_${VERSION}_aarch64.dmg "ZeroLimit_${VERSION}_macOS_aarch64.dmg"
mv src-tauri/target/aarch64-apple-darwin/release/bundle/macos/ZeroLimit.app.tar.gz "ZeroLimit_${VERSION}_macOS_aarch64.app.tar.gz"
mv src-tauri/target/aarch64-apple-darwin/release/bundle/macos/ZeroLimit.app.tar.gz.sig "ZeroLimit_${VERSION}_macOS_aarch64.app.tar.gz.sig"
- name: Upload artifacts to release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: true
files: |
ZeroLimit_*_macOS_aarch64.dmg
ZeroLimit_*_macOS_aarch64.app.tar.gz
ZeroLimit_*_macOS_aarch64.app.tar.gz.sig
- name: Upload signatures for latest.json
uses: actions/upload-artifact@v4
with:
name: signatures-macos-arm64
path: ZeroLimit_*_macOS_aarch64.app.tar.gz.sig
# ===========================================
# 6. Build Linux x64
# ===========================================
build-linux:
needs: create-release
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: main
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libssl-dev \
libgtk-3-dev \
libsoup-3.0-dev \
javascriptcoregtk-4.1-dev
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache Cargo
uses: actions/cache@v4
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
src-tauri/target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Install frontend dependencies
run: pnpm install
- name: Build Tauri
run: pnpm tauri build
- name: Rename and Prepare artifacts
run: |
VERSION="${{ needs.create-release.outputs.version }}"
echo "=== Listing build output directory ==="
ls -R src-tauri/target/release/bundle/
# Debian (using wildcard for safety)
find src-tauri/target/release/bundle/deb/ -name "*_${VERSION}_amd64.deb" -exec mv {} "ZeroLimit_${VERSION}_Linux_x64.deb" \;
# RPM (using wildcard for safety)
find src-tauri/target/release/bundle/rpm/ -name "*-${VERSION}-1.x86_64.rpm" -exec mv {} "ZeroLimit_${VERSION}_Linux_x64.rpm" \;
# AppImage (using wildcard for safety)
find src-tauri/target/release/bundle/appimage/ -name "*_${VERSION}_amd64.AppImage" -exec mv {} "ZeroLimit_${VERSION}_Linux_x64.AppImage" \;
# AppImage.tar.gz and signature (updater artifacts)
find src-tauri/target/release/bundle/appimage/ -name "*.AppImage.tar.gz" ! -name "*.sig" -exec mv {} "ZeroLimit_${VERSION}_Linux_x64.AppImage.tar.gz" \;
find src-tauri/target/release/bundle/appimage/ -name "*.AppImage.tar.gz.sig" -exec mv {} "ZeroLimit_${VERSION}_Linux_x64.AppImage.tar.gz.sig" \;
echo "=== Prepared artifacts in workspace ==="
ls -la ZeroLimit_* || echo "No artifacts found!"
- name: Upload artifacts to release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: true
fail_on_unmatched_files: false
files: |
ZeroLimit_*_Linux_x64.deb
ZeroLimit_*_Linux_x64.rpm
ZeroLimit_*_Linux_x64.AppImage
ZeroLimit_*_Linux_x64.AppImage.tar.gz
ZeroLimit_*_Linux_x64.AppImage.tar.gz.sig
- name: Upload signatures for latest.json
uses: actions/upload-artifact@v4
with:
name: signatures-linux
path: ZeroLimit_*_Linux_x64.AppImage.tar.gz.sig
if-no-files-found: warn
# ===========================================
# 7. Publish Release + Generate latest.json
# ===========================================
publish-release:
needs: [create-release, build-windows-x64, build-windows-arm64, build-macos-x64, build-macos-arm64, build-linux]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download all signatures
uses: actions/download-artifact@v4
with:
pattern: signatures-*
merge-multiple: true
path: signatures
- name: List signatures (debug)
run: find signatures -type f | sort
- name: Generate latest.json
run: |
VERSION="${{ needs.create-release.outputs.version }}"
REPO="${{ github.repository }}"
DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Read signature files
WIN_X64_SIG=$(find signatures -name "*Windows_x64-setup.exe.sig" | head -1 | xargs cat 2>/dev/null || echo "")
WIN_ARM64_SIG=$(find signatures -name "*Windows_arm64-setup.exe.sig" | head -1 | xargs cat 2>/dev/null || echo "")
MACOS_ARM64_SIG=$(find signatures -name "*macOS_aarch64.app.tar.gz.sig" | head -1 | xargs cat 2>/dev/null || echo "")
MACOS_X64_SIG=$(find signatures -name "*macOS_x64.app.tar.gz.sig" | head -1 | xargs cat 2>/dev/null || echo "")
LINUX_SIG=$(find signatures -name "*Linux_x64.AppImage.tar.gz.sig" | head -1 | xargs cat 2>/dev/null || echo "")
# Build platforms JSON dynamically
PLATFORMS="{"
if [ -n "$WIN_X64_SIG" ]; then
PLATFORMS="$PLATFORMS\"windows-x86_64\":{\"signature\":\"$WIN_X64_SIG\",\"url\":\"https://github.com/$REPO/releases/download/v$VERSION/ZeroLimit_${VERSION}_Windows_x64-setup.exe\"},"
fi
if [ -n "$WIN_ARM64_SIG" ]; then
PLATFORMS="$PLATFORMS\"windows-aarch64\":{\"signature\":\"$WIN_ARM64_SIG\",\"url\":\"https://github.com/$REPO/releases/download/v$VERSION/ZeroLimit_${VERSION}_Windows_arm64-setup.exe\"},"
fi
if [ -n "$MACOS_ARM64_SIG" ]; then
PLATFORMS="$PLATFORMS\"darwin-aarch64\":{\"signature\":\"$MACOS_ARM64_SIG\",\"url\":\"https://github.com/$REPO/releases/download/v$VERSION/ZeroLimit_${VERSION}_macOS_aarch64.app.tar.gz\"},"
fi
if [ -n "$MACOS_X64_SIG" ]; then
PLATFORMS="$PLATFORMS\"darwin-x86_64\":{\"signature\":\"$MACOS_X64_SIG\",\"url\":\"https://github.com/$REPO/releases/download/v$VERSION/ZeroLimit_${VERSION}_macOS_x64.app.tar.gz\"},"
fi
if [ -n "$LINUX_SIG" ]; then
PLATFORMS="$PLATFORMS\"linux-x86_64\":{\"signature\":\"$LINUX_SIG\",\"url\":\"https://github.com/$REPO/releases/download/v$VERSION/ZeroLimit_${VERSION}_Linux_x64.AppImage.tar.gz\"},"
fi
# Remove trailing comma and close
PLATFORMS="${PLATFORMS%,}}"
# Write latest.json
echo "{\"version\":\"$VERSION\",\"notes\":\"See release notes on GitHub\",\"pub_date\":\"$DATE\",\"platforms\":$PLATFORMS}" | jq '.' > latest.json
echo "Generated latest.json:"
cat latest.json
- name: Upload latest.json
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.create-release.outputs.version }}
draft: false
files: latest.json