Skip to content

Build and Release

Build and Release #1

name: Build and Release
on:
release:
types: [published]
workflow_dispatch:
inputs:
draft_release:
description: 'Create draft release'
required: false
type: boolean
default: false
version:
description: 'Version tag (optional, uses run number if empty)'
required: false
type: string
jobs:
build-linux:
runs-on: ubuntu-latest
strategy:
matrix:
arch: [x64, arm64]
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install dependencies
run: |
pnpm config set fund false
pnpm install --frozen-lockfile
- name: Build Linux ${{ matrix.arch }}
run: |
if [ "${{ matrix.arch }}" = "x64" ]; then
pnpm run build:linux --x64
else
pnpm run build:linux --${{ matrix.arch }}
fi
- name: Upload Linux artifacts
uses: actions/upload-artifact@v4
with:
name: p-stream-linux-${{ matrix.arch }}
path: dist/*.AppImage
retention-days: 30
build-windows:
runs-on: windows-latest
strategy:
matrix:
arch: [x64, arm64]
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install dependencies
run: |
pnpm config set fund false
pnpm install --frozen-lockfile
- name: Build Windows ${{ matrix.arch }}
shell: bash
run: |
if [ "${{ matrix.arch }}" = "x64" ]; then
pnpm run build:win --x64
else
pnpm run build:win --${{ matrix.arch }}
fi
- name: Upload Windows artifacts
uses: actions/upload-artifact@v4
with:
name: p-stream-windows-${{ matrix.arch }}
path: |
dist/*.exe
dist/*.zip
retention-days: 30
build-macos:
runs-on: macos-latest
strategy:
matrix:
arch: [x64, arm64]
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install dependencies
run: |
pnpm config set fund false
pnpm install --frozen-lockfile
- name: Build macOS ${{ matrix.arch }}
run: |
if [ "${{ matrix.arch }}" = "x64" ]; then
pnpm run build:mac --x64
else
pnpm run build:mac --${{ matrix.arch }}
fi
- name: Upload macOS artifacts
uses: actions/upload-artifact@v4
with:
name: p-stream-macos-${{ matrix.arch }}
path: |
dist/*.dmg
dist/*.zip
retention-days: 30
release:
needs: [build-linux, build-windows, build-macos]
runs-on: ubuntu-latest
if: github.event_name == 'release' || github.event.inputs.draft_release == 'true'
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
- name: Create draft release (if triggered manually)
if: github.event.inputs.draft_release == 'true'
run: |
VERSION_TAG="${{ github.event.inputs.version }}"
if [ -z "$VERSION_TAG" ]; then
VERSION_TAG="draft-${{ github.run_number }}"
fi
gh release create "$VERSION_TAG" \
--title "Draft Release ${{ github.run_number }}" \
--notes "Automated draft release" \
--draft \
--prerelease
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Install dependencies
run: |
pnpm config set fund false
pnpm install --frozen-lockfile
- name: Upload Release Assets and Generate Update Metadata
run: |
# Determine release tag
if [ "${{ github.event.inputs.draft_release }}" = "true" ]; then
VERSION_TAG="${{ github.event.inputs.version }}"
if [ -z "$VERSION_TAG" ]; then
RELEASE_TAG="draft-${{ github.run_number }}"
else
RELEASE_TAG="$VERSION_TAG"
fi
else
RELEASE_TAG="${{ github.event.release.tag_name }}"
fi
echo "Uploading to release: $RELEASE_TAG"
# Extract version from package.json
VERSION=$(node -p "require('./package.json').version")
echo "App version: $VERSION"
# Find and upload all built artifacts, and collect info for update files
mkdir -p update-metadata
# First pass: Upload all files and collect metadata (prefer x64)
LINUX_FILE=""
WINDOWS_FILE=""
MACOS_FILE=""
LINUX_SHA512=""
WINDOWS_SHA512=""
MACOS_SHA512=""
LINUX_SIZE=""
WINDOWS_SIZE=""
MACOS_SIZE=""
for file in ./artifacts/*/*; do
if [ -f "$file" ]; then
filename=$(basename "$file")
echo "Uploading $filename..."
gh release upload "$RELEASE_TAG" "$file" --clobber
# Get file size and SHA512 for update metadata
SIZE=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null || echo "0")
# Generate SHA512 hash (required for electron-updater)
if command -v shasum > /dev/null; then
SHA512=$(shasum -a 512 "$file" | cut -d' ' -f1)
elif command -v sha512sum > /dev/null; then
SHA512=$(sha512sum "$file" | cut -d' ' -f1)
else
echo "Error: Cannot generate SHA512 hash. Install shasum or sha512sum."
exit 1
fi
# Determine platform and collect file info (prefer x64)
if [[ "$filename" == *.AppImage ]]; then
if [[ "$filename" == *x64* ]] || [ -z "$LINUX_FILE" ]; then
LINUX_FILE="$filename"
LINUX_SHA512="$SHA512"
LINUX_SIZE="$SIZE"
fi
elif [[ "$filename" == *.exe ]]; then
if [[ "$filename" == *x64* ]] || [ -z "$WINDOWS_FILE" ]; then
WINDOWS_FILE="$filename"
WINDOWS_SHA512="$SHA512"
WINDOWS_SIZE="$SIZE"
fi
elif [[ "$filename" == *.dmg ]]; then
if [ -z "$MACOS_FILE" ]; then
MACOS_FILE="$filename"
MACOS_SHA512="$SHA512"
MACOS_SIZE="$SIZE"
fi
elif [[ "$filename" == *.zip ]]; then
# Only use .zip if .dmg wasn't found
if [ -z "$MACOS_FILE" ]; then
MACOS_FILE="$filename"
MACOS_SHA512="$SHA512"
MACOS_SIZE="$SIZE"
fi
fi
fi
done
# Generate update metadata files
RELEASE_DATE=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
if [ -n "$LINUX_FILE" ]; then
{
echo "version: $VERSION"
echo "files:"
echo " - url: $LINUX_FILE"
echo " sha512: $LINUX_SHA512"
echo " size: $LINUX_SIZE"
echo "path: $LINUX_FILE"
echo "sha512: $LINUX_SHA512"
echo "releaseDate: $RELEASE_DATE"
} > "update-metadata/latest-linux.yml"
fi
if [ -n "$WINDOWS_FILE" ]; then
{
echo "version: $VERSION"
echo "files:"
echo " - url: $WINDOWS_FILE"
echo " sha512: $WINDOWS_SHA512"
echo " size: $WINDOWS_SIZE"
echo "path: $WINDOWS_FILE"
echo "sha512: $WINDOWS_SHA512"
echo "releaseDate: $RELEASE_DATE"
} > "update-metadata/latest.yml"
fi
if [ -n "$MACOS_FILE" ]; then
{
echo "version: $VERSION"
echo "files:"
echo " - url: $MACOS_FILE"
echo " sha512: $MACOS_SHA512"
echo " size: $MACOS_SIZE"
echo "path: $MACOS_FILE"
echo "sha512: $MACOS_SHA512"
echo "releaseDate: $RELEASE_DATE"
} > "update-metadata/latest-mac.yml"
fi
# Upload update metadata files
if ls update-metadata/*.yml 1> /dev/null 2>&1; then
echo "Uploading update metadata files..."
for yml in update-metadata/*.yml; do
filename=$(basename "$yml")
echo "Uploading $filename..."
gh release upload "$RELEASE_TAG" "$yml" --clobber
done
echo "Update metadata files uploaded successfully"
else
echo "Warning: No update metadata files were generated"
echo "This may cause update checks to fail"
fi
env:
GH_TOKEN: ${{ secrets.GH_TOKEN }}