Skip to content

Prepare release of v0.13.2-beta.4 #34

Prepare release of v0.13.2-beta.4

Prepare release of v0.13.2-beta.4 #34

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
tag:
description: 'Tag to release (e.g., v0.11.3)'
required: true
type: string
env:
# Use input tag for workflow_dispatch, or ref_name for push events
RELEASE_TAG: ${{ inputs.tag || github.ref_name }}
jobs:
create-release:
name: Create Release
runs-on: ubuntu-latest
permissions:
contents: write
outputs:
is_prerelease: ${{ steps.check_prerelease.outputs.is_prerelease }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Check if prerelease
id: check_prerelease
run: |
if [[ "${{ env.RELEASE_TAG }}" =~ -(alpha|beta|rc)\. ]]; then
echo "is_prerelease=true" >> $GITHUB_OUTPUT
echo "Detected prerelease tag: ${{ env.RELEASE_TAG }}"
else
echo "is_prerelease=false" >> $GITHUB_OUTPUT
echo "Detected stable release tag: ${{ env.RELEASE_TAG }}"
fi
- name: Create or Update Release
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ env.RELEASE_TAG }}
body_path: RELEASE_NOTES.md
draft: false
prerelease: ${{ steps.check_prerelease.outputs.is_prerelease == 'true' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-macos:
name: Build macOS (${{ matrix.arch }})
needs: create-release
runs-on: macos-latest
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- arch: aarch64
target: aarch64-apple-darwin
- arch: x86_64
target: x86_64-apple-darwin
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: apps/fluux/src-tauri
key: ${{ matrix.target }}
- name: Install dependencies
run: npm ci
- name: Build SDK
run: npm run build:sdk
- name: Read release notes
id: release_notes
run: |
if [ -f RELEASE_NOTES.md ]; then
NOTES=$(cat RELEASE_NOTES.md)
else
NOTES="See the [CHANGELOG](https://github.com/processone/fluux-messenger/blob/main/CHANGELOG.md) for details."
fi
echo "notes<<EOF" >> $GITHUB_OUTPUT
echo "$NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Patch version for Tauri semver compatibility
run: |
# Tauri v2 requires strict semver (X.Y.Z) — prerelease suffixes are rejected
# Strip prerelease suffix: 0.13.2-beta.1 → 0.13.2
# For stable versions (no hyphen), this is a no-op
VERSION="${RELEASE_TAG#v}"
if [[ "$VERSION" == *-* ]]; then
BASE_VERSION="${VERSION%%-*}"
echo "Patching version for Tauri build: $VERSION → $BASE_VERSION"
sed -i '' "s|\"version\": \".*\"|\"version\": \"$BASE_VERSION\"|" apps/fluux/src-tauri/tauri.conf.json
sed -i '' "s|^version = \".*\"|version = \"$BASE_VERSION\"|" apps/fluux/src-tauri/Cargo.toml
else
echo "Stable version $VERSION — no patching needed"
fi
- name: Build Tauri app
uses: tauri-apps/tauri-action@v0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
with:
projectPath: apps/fluux
tagName: ${{ env.RELEASE_TAG }}
releaseName: 'Fluux Messenger ${{ env.RELEASE_TAG }}'
releaseBody: ${{ steps.release_notes.outputs.notes }}
releaseDraft: false
prerelease: ${{ needs.create-release.outputs.is_prerelease == 'true' }}
includeUpdaterJson: false
args: --target ${{ matrix.target }}
build-windows:
name: Build Windows
needs: create-release
runs-on: windows-latest
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: apps/fluux/src-tauri
- name: Install dependencies
run: npm ci
- name: Build SDK
run: npm run build:sdk
- name: Read release notes
id: release_notes
shell: bash
run: |
if [ -f RELEASE_NOTES.md ]; then
NOTES=$(cat RELEASE_NOTES.md)
else
NOTES="See the [CHANGELOG](https://github.com/processone/fluux-messenger/blob/main/CHANGELOG.md) for details."
fi
echo "notes<<EOF" >> $GITHUB_OUTPUT
echo "$NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Patch version for Tauri semver compatibility
shell: bash
run: |
# Tauri v2 requires strict semver (X.Y.Z) — prerelease suffixes are rejected
# Strip prerelease suffix: 0.13.2-beta.1 → 0.13.2
# For stable versions (no hyphen), this is a no-op
VERSION="${RELEASE_TAG#v}"
if [[ "$VERSION" == *-* ]]; then
BASE_VERSION="${VERSION%%-*}"
echo "Patching version for Tauri build: $VERSION → $BASE_VERSION"
sed -i "s|\"version\": \".*\"|\"version\": \"$BASE_VERSION\"|" apps/fluux/src-tauri/tauri.conf.json
sed -i "s|^version = \".*\"|version = \"$BASE_VERSION\"|" apps/fluux/src-tauri/Cargo.toml
else
echo "Stable version $VERSION — no patching needed"
fi
- name: Build Tauri 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: apps/fluux
tagName: ${{ env.RELEASE_TAG }}
releaseName: 'Fluux Messenger ${{ env.RELEASE_TAG }}'
releaseBody: ${{ steps.release_notes.outputs.notes }}
releaseDraft: false
prerelease: ${{ needs.create-release.outputs.is_prerelease == 'true' }}
includeUpdaterJson: false # Generated by rename-assets script with all platforms
- name: Sign Windows executables with Azure Trusted Signing
uses: azure/trusted-signing-action@v0.5.1
with:
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
endpoint: ${{ secrets.AZURE_SIGNING_ENDPOINT }}
trusted-signing-account-name: ${{ secrets.AZURE_CODE_SIGNING_ACCOUNT }}
certificate-profile-name: ${{ secrets.AZURE_CERT_PROFILE_NAME }}
files-folder: apps/fluux/src-tauri/target/release/bundle
files-folder-filter: exe,msi
files-folder-recurse: true
file-digest: SHA256
timestamp-rfc3161: http://timestamp.acs.microsoft.com
timestamp-digest: SHA256
- name: Re-sign Authenticode-signed binaries for Tauri updater
shell: bash
env:
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
run: |
# After Azure Trusted Signing modifies the binaries (embeds Authenticode signature),
# the original .sig files are stale. Re-generate them against the signed binaries.
# Note: tauri signer CLI reads TAURI_PRIVATE_KEY (not TAURI_SIGNING_PRIVATE_KEY),
# while tauri-action handles the mapping internally.
npx tauri signer sign apps/fluux/src-tauri/target/release/bundle/nsis/*.exe
npx tauri signer sign apps/fluux/src-tauri/target/release/bundle/msi/*.msi
- name: Re-upload signed artifacts
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release upload ${{ env.RELEASE_TAG }} apps/fluux/src-tauri/target/release/bundle/nsis/*.exe --clobber
gh release upload ${{ env.RELEASE_TAG }} apps/fluux/src-tauri/target/release/bundle/nsis/*.exe.sig --clobber
gh release upload ${{ env.RELEASE_TAG }} apps/fluux/src-tauri/target/release/bundle/msi/*.msi --clobber
gh release upload ${{ env.RELEASE_TAG }} apps/fluux/src-tauri/target/release/bundle/msi/*.msi.sig --clobber
build-linux:
name: Build Linux (${{ matrix.arch }})
needs: create-release
runs-on: ${{ matrix.runner }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-22.04
target: x86_64-unknown-linux-gnu
deb_arch: amd64
- arch: aarch64
runner: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
deb_arch: arm64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libxss-dev \
devscripts \
debhelper
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: apps/fluux/src-tauri
key: ${{ matrix.target }}
- name: Install dependencies
run: npm ci
- name: Build SDK
run: npm run build:sdk
- name: Read release notes
id: release_notes
run: |
if [ -f RELEASE_NOTES.md ]; then
NOTES=$(cat RELEASE_NOTES.md)
else
NOTES="See the [CHANGELOG](https://github.com/processone/fluux-messenger/blob/main/CHANGELOG.md) for details."
fi
echo "notes<<EOF" >> $GITHUB_OUTPUT
echo "$NOTES" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Patch version for Tauri semver compatibility
run: |
# Tauri v2 requires strict semver (X.Y.Z) — prerelease suffixes are rejected
# Strip prerelease suffix: 0.13.2-beta.1 → 0.13.2
# For stable versions (no hyphen), this is a no-op
VERSION="${RELEASE_TAG#v}"
if [[ "$VERSION" == *-* ]]; then
BASE_VERSION="${VERSION%%-*}"
echo "Patching version for Tauri build: $VERSION → $BASE_VERSION"
sed -i "s|\"version\": \".*\"|\"version\": \"$BASE_VERSION\"|" apps/fluux/src-tauri/tauri.conf.json
sed -i "s|^version = \".*\"|version = \"$BASE_VERSION\"|" apps/fluux/src-tauri/Cargo.toml
else
echo "Stable version $VERSION — no patching needed"
fi
- name: Build Tauri binary
run: |
cd apps/fluux
# Native build on matching runner (x86 on ubuntu-22.04, arm on ubuntu-22.04-arm)
npm run tauri build -- --no-bundle
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
- name: Create tarball for Arch Linux
run: |
VERSION="${RELEASE_TAG#v}"
ARCH="${{ matrix.arch }}"
TARBALL_NAME="fluux-messenger-${VERSION}-linux-${ARCH}.tar.gz"
mkdir -p tarball-staging/fluux-messenger
# Copy binary
cp apps/fluux/src-tauri/target/release/fluux tarball-staging/fluux-messenger/fluux-messenger
# Copy desktop file and icons
cp packaging/debian/fluux-messenger.desktop tarball-staging/fluux-messenger/
cp apps/fluux/src-tauri/icons/128x128.png tarball-staging/fluux-messenger/fluux-messenger.png
cp apps/fluux/src-tauri/icons/256x256.png tarball-staging/fluux-messenger/fluux-messenger-256.png
# Create tarball
mkdir -p dist
tar -czvf "dist/${TARBALL_NAME}" -C tarball-staging fluux-messenger
- name: Upload tarball to Release
uses: softprops/action-gh-release@v1
with:
files: dist/*.tar.gz
tag_name: ${{ env.RELEASE_TAG }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build .deb package
run: |
# Copy debian directory from packaging/ to root (required by dpkg-buildpackage)
cp -r packaging/debian .
# Point to pre-built binary (debian/rules will skip build)
# Native builds output to target/release/, not target/<triple>/release/
export FLUUX_BINARY="apps/fluux/src-tauri/target/release/fluux"
# Update debian/changelog version from release tag
# Convert pre-release for Debian (~ sorts before release, so 0.13.2~beta.1 < 0.13.2)
# Note: cannot use ${VERSION//-/~} because bash 5+ applies tilde expansion
# to the replacement string, turning ~ into $HOME
VERSION="${RELEASE_TAG#v}"
DEB_VERSION=$(echo "$VERSION" | sed 's/-/~/g')
sed -i "1s#([^)]*)#($DEB_VERSION-1)#" debian/changelog
# Build the .deb package (-d skips build dependency check since we use pre-built binary)
dpkg-buildpackage -d -uc -us -b
# Move .deb to a known location (dpkg already includes architecture in filename)
mkdir -p dist
mv ../fluux-messenger_*.deb dist/
- name: Upload .deb to Release
uses: softprops/action-gh-release@v1
with:
files: dist/*.deb
tag_name: ${{ env.RELEASE_TAG }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build Flatpak
run: |
# Install flatpak-builder
sudo apt-get install -y flatpak flatpak-builder
flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
flatpak install --user -y flathub org.gnome.Platform//47 org.gnome.Sdk//47
VERSION="${RELEASE_TAG#v}"
ARCH="${{ matrix.arch }}"
# Prepare build directory with sources
mkdir -p flatpak-build
cp apps/fluux/src-tauri/target/release/fluux flatpak-build/fluux-messenger
cp packaging/debian/fluux-messenger.desktop flatpak-build/
cp apps/fluux/src-tauri/icons/128x128.png flatpak-build/fluux-messenger.png
cp apps/fluux/src-tauri/icons/256x256.png flatpak-build/fluux-messenger-256.png
cp packaging/flatpak/com.processone.fluux.metainfo.xml flatpak-build/
cp packaging/flatpak/com.processone.fluux.yaml flatpak-build/
# Build Flatpak
cd flatpak-build
flatpak-builder --user --force-clean --disable-updates --repo=repo build-dir com.processone.fluux.yaml
# Create single-file bundle
flatpak build-bundle repo "fluux-messenger-${VERSION}-linux-${ARCH}.flatpak" com.processone.fluux
# Move to dist
mv *.flatpak ../dist/
- name: Upload Flatpak to Release
uses: softprops/action-gh-release@v1
with:
files: dist/*.flatpak
tag_name: ${{ env.RELEASE_TAG }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
build-linux-rpm:
name: Build Linux RPM (${{ matrix.arch }})
needs: create-release
runs-on: ${{ matrix.runner }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-22.04
target: x86_64-unknown-linux-gnu
rpm_arch: x86_64
- arch: aarch64
runner: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
rpm_arch: aarch64
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Install Linux dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libxss-dev \
rpm
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Rust cache
uses: Swatinem/rust-cache@v2
with:
workspaces: apps/fluux/src-tauri
key: ${{ matrix.target }}
- name: Install dependencies
run: npm ci
- name: Build SDK
run: npm run build:sdk
- name: Patch version for Tauri semver compatibility
run: |
# Tauri v2 requires strict semver (X.Y.Z) — prerelease suffixes are rejected
# Strip prerelease suffix: 0.13.2-beta.1 → 0.13.2
# For stable versions (no hyphen), this is a no-op
VERSION="${RELEASE_TAG#v}"
if [[ "$VERSION" == *-* ]]; then
BASE_VERSION="${VERSION%%-*}"
echo "Patching version for Tauri build: $VERSION → $BASE_VERSION"
sed -i "s|\"version\": \".*\"|\"version\": \"$BASE_VERSION\"|" apps/fluux/src-tauri/tauri.conf.json
sed -i "s|^version = \".*\"|version = \"$BASE_VERSION\"|" apps/fluux/src-tauri/Cargo.toml
else
echo "Stable version $VERSION — no patching needed"
fi
- name: Build Tauri binary
run: |
cd apps/fluux
npm run tauri build -- --no-bundle
env:
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
- name: Build .rpm package
run: |
VERSION="${RELEASE_TAG#v}"
# Convert pre-release version for RPM (hyphens not allowed in Version field)
# 0.13.2-beta.1 → RPM_VERSION=0.13.2, RPM_RELEASE=0.1.beta.1
# 0.13.2 → RPM_VERSION=0.13.2, RPM_RELEASE=1
if [[ "$VERSION" == *-* ]]; then
RPM_VERSION="${VERSION%%-*}"
RPM_PRERELEASE="${VERSION#*-}"
RPM_RELEASE="0.1.${RPM_PRERELEASE//-/.}"
else
RPM_VERSION="$VERSION"
RPM_RELEASE="1"
fi
# Setup RPM build directories
mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
# Create source tarball for rpmbuild (directory name must match %{version} in spec)
mkdir -p "fluux-messenger-${RPM_VERSION}"
cp apps/fluux/src-tauri/target/release/fluux "fluux-messenger-${RPM_VERSION}/fluux-messenger"
cp packaging/debian/fluux-messenger.desktop "fluux-messenger-${RPM_VERSION}/"
mkdir -p "fluux-messenger-${RPM_VERSION}/icons"
cp apps/fluux/src-tauri/icons/32x32.png "fluux-messenger-${RPM_VERSION}/icons/"
cp apps/fluux/src-tauri/icons/64x64.png "fluux-messenger-${RPM_VERSION}/icons/"
cp apps/fluux/src-tauri/icons/128x128.png "fluux-messenger-${RPM_VERSION}/icons/"
cp apps/fluux/src-tauri/icons/256x256.png "fluux-messenger-${RPM_VERSION}/icons/"
tar czvf ~/rpmbuild/SOURCES/fluux-messenger-${RPM_VERSION}.tar.gz "fluux-messenger-${RPM_VERSION}"
# Copy and update spec file
cp packaging/rpm/fluux-messenger.spec ~/rpmbuild/SPECS/
sed -i "s/^Version:.*/Version: ${RPM_VERSION}/" ~/rpmbuild/SPECS/fluux-messenger.spec
sed -i "s/^Release:.*/Release: ${RPM_RELEASE}%{?dist}/" ~/rpmbuild/SPECS/fluux-messenger.spec
# Build RPM
rpmbuild -bb ~/rpmbuild/SPECS/fluux-messenger.spec --target ${{ matrix.rpm_arch }}
# Move RPM to dist
mkdir -p dist
mv ~/rpmbuild/RPMS/${{ matrix.rpm_arch }}/*.rpm dist/
- name: Upload .rpm to Release
uses: softprops/action-gh-release@v1
with:
files: dist/*.rpm
tag_name: ${{ env.RELEASE_TAG }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Final job to rename all assets to consistent, user-friendly names
rename-assets:
name: Rename Release Assets
runs-on: ubuntu-latest
needs: [create-release, build-macos, build-windows, build-linux, build-linux-rpm]
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ env.RELEASE_TAG }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Rename assets and update latest.json
run: |
ARGS="${{ env.RELEASE_TAG }}"
if [ "${{ needs.create-release.outputs.is_prerelease }}" = "true" ]; then
ARGS="$ARGS --skip-updater"
fi
node scripts/rename-release-assets.js $ARGS
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}