1165 lines
44 KiB
YAML
1165 lines
44 KiB
YAML
name: Build and Push Electron App
|
||
|
||
on:
|
||
workflow_dispatch:
|
||
inputs:
|
||
build_type:
|
||
description: "Platform to build for"
|
||
required: true
|
||
default: "all"
|
||
type: choice
|
||
options:
|
||
- all
|
||
- windows
|
||
- linux
|
||
- macos
|
||
artifact_destination:
|
||
description: "What to do with the built app"
|
||
required: true
|
||
default: "file"
|
||
type: choice
|
||
options:
|
||
- none
|
||
- file
|
||
- release
|
||
- submit
|
||
|
||
jobs:
|
||
build-windows:
|
||
runs-on: windows-latest
|
||
if: github.event.inputs.build_type == 'all' || github.event.inputs.build_type == 'windows' || github.event.inputs.build_type == ''
|
||
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 1
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: "20"
|
||
cache: "npm"
|
||
|
||
- name: Install dependencies
|
||
run: |
|
||
# Retry npm ci up to 3 times on failure
|
||
$maxAttempts = 3
|
||
$attempt = 1
|
||
while ($attempt -le $maxAttempts) {
|
||
try {
|
||
npm ci
|
||
break
|
||
} catch {
|
||
if ($attempt -eq $maxAttempts) {
|
||
Write-Error "npm ci failed after $maxAttempts attempts"
|
||
exit 1
|
||
}
|
||
Write-Host "npm ci attempt $attempt failed, retrying in 10 seconds..."
|
||
Start-Sleep -Seconds 10
|
||
$attempt++
|
||
}
|
||
}
|
||
|
||
- name: Get version
|
||
id: package-version
|
||
run: |
|
||
$VERSION = (Get-Content package.json | ConvertFrom-Json).version
|
||
echo "version=$VERSION" >> $env:GITHUB_OUTPUT
|
||
echo "Building version: $VERSION"
|
||
|
||
- name: Build Windows (All Architectures)
|
||
run: npm run build && npx electron-builder --win --x64 --ia32
|
||
|
||
- name: List release files
|
||
run: |
|
||
echo "Contents of release directory:"
|
||
dir release
|
||
|
||
- name: Upload Windows x64 NSIS Installer
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_x64_*_nsis.exe') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_windows_x64_nsis
|
||
path: release/*_x64_*_nsis.exe
|
||
retention-days: 30
|
||
|
||
- name: Upload Windows ia32 NSIS Installer
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_ia32_*_nsis.exe') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_windows_ia32_nsis
|
||
path: release/*_ia32_*_nsis.exe
|
||
retention-days: 30
|
||
|
||
- name: Upload Windows x64 MSI Installer
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_x64_*_msi.msi') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_windows_x64_msi
|
||
path: release/*_x64_*_msi.msi
|
||
retention-days: 30
|
||
|
||
- name: Upload Windows ia32 MSI Installer
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_ia32_*_msi.msi') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_windows_ia32_msi
|
||
path: release/*_ia32_*_msi.msi
|
||
retention-days: 30
|
||
|
||
- name: Create Windows x64 Portable zip
|
||
if: hashFiles('release/win-unpacked/*') != ''
|
||
run: |
|
||
$VERSION = "${{ steps.package-version.outputs.version }}"
|
||
Compress-Archive -Path "release\win-unpacked\*" -DestinationPath "termix_windows_x64_${VERSION}_portable.zip"
|
||
|
||
- name: Create Windows ia32 Portable zip
|
||
if: hashFiles('release/win-ia32-unpacked/*') != ''
|
||
run: |
|
||
$VERSION = "${{ steps.package-version.outputs.version }}"
|
||
Compress-Archive -Path "release\win-ia32-unpacked\*" -DestinationPath "termix_windows_ia32_${VERSION}_portable.zip"
|
||
|
||
- name: Upload Windows x64 Portable
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('termix_windows_x64_*_portable.zip') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_windows_x64_portable
|
||
path: termix_windows_x64_*_portable.zip
|
||
retention-days: 30
|
||
|
||
- name: Upload Windows ia32 Portable
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('termix_windows_ia32_*_portable.zip') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_windows_ia32_portable
|
||
path: termix_windows_ia32_*_portable.zip
|
||
retention-days: 30
|
||
|
||
build-linux:
|
||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||
if: github.event.inputs.build_type == 'all' || github.event.inputs.build_type == 'linux' || github.event.inputs.build_type == ''
|
||
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 1
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: "20"
|
||
cache: "npm"
|
||
|
||
- name: Install dependencies
|
||
run: |
|
||
# Retry npm ci up to 3 times on failure
|
||
for i in 1 2 3; do
|
||
if npm ci; then
|
||
break
|
||
else
|
||
if [ $i -eq 3 ]; then
|
||
echo "npm ci failed after 3 attempts"
|
||
exit 1
|
||
fi
|
||
echo "npm ci attempt $i failed, retrying in 10 seconds..."
|
||
sleep 10
|
||
fi
|
||
done
|
||
npm install --force @rollup/rollup-linux-x64-gnu
|
||
npm install --force @rollup/rollup-linux-arm64-gnu
|
||
npm install --force @rollup/rollup-linux-arm-gnueabihf
|
||
|
||
- name: Build Linux (All Architectures)
|
||
run: npm run build && npx electron-builder --linux --x64 --arm64 --armv7l
|
||
|
||
- name: Rename tar.gz files to match convention
|
||
run: |
|
||
VERSION=$(node -p "require('./package.json').version")
|
||
cd release
|
||
|
||
# Rename x64 tar.gz if it exists
|
||
if [ -f "termix-${VERSION}.tar.gz" ]; then
|
||
mv "termix-${VERSION}.tar.gz" "termix_linux_x64_${VERSION}_portable.tar.gz"
|
||
echo "Renamed x64 tar.gz"
|
||
fi
|
||
|
||
# Rename arm64 tar.gz if it exists
|
||
if [ -f "termix-${VERSION}-arm64.tar.gz" ]; then
|
||
mv "termix-${VERSION}-arm64.tar.gz" "termix_linux_arm64_${VERSION}_portable.tar.gz"
|
||
echo "Renamed arm64 tar.gz"
|
||
fi
|
||
|
||
# Rename armv7l tar.gz if it exists
|
||
if [ -f "termix-${VERSION}-armv7l.tar.gz" ]; then
|
||
mv "termix-${VERSION}-armv7l.tar.gz" "termix_linux_armv7l_${VERSION}_portable.tar.gz"
|
||
echo "Renamed armv7l tar.gz"
|
||
fi
|
||
|
||
cd ..
|
||
|
||
- name: List release files
|
||
run: |
|
||
echo "Contents of release directory:"
|
||
ls -la release/
|
||
|
||
- name: Upload Linux x64 AppImage
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_x64_*_appimage.AppImage') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_x64_appimage
|
||
path: release/*_x64_*_appimage.AppImage
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux arm64 AppImage
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_arm64_*_appimage.AppImage') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_arm64_appimage
|
||
path: release/*_arm64_*_appimage.AppImage
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux x64 DEB
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_x64_*_deb.deb') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_x64_deb
|
||
path: release/*_x64_*_deb.deb
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux arm64 DEB
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_arm64_*_deb.deb') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_arm64_deb
|
||
path: release/*_arm64_*_deb.deb
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux armv7l DEB
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_armv7l_*_deb.deb') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_armv7l_deb
|
||
path: release/*_armv7l_*_deb.deb
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux x64 tar.gz
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_x64_*_portable.tar.gz') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_x64_portable
|
||
path: release/*_x64_*_portable.tar.gz
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux arm64 tar.gz
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_arm64_*_portable.tar.gz') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_arm64_portable
|
||
path: release/*_arm64_*_portable.tar.gz
|
||
retention-days: 30
|
||
|
||
- name: Upload Linux armv7l tar.gz
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_armv7l_*_portable.tar.gz') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_linux_armv7l_portable
|
||
path: release/*_armv7l_*_portable.tar.gz
|
||
retention-days: 30
|
||
|
||
build-macos:
|
||
runs-on: macos-latest
|
||
if: github.event.inputs.build_type == 'macos' || github.event.inputs.build_type == 'all'
|
||
needs: []
|
||
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 1
|
||
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: "20"
|
||
cache: "npm"
|
||
|
||
- name: Install dependencies
|
||
run: |
|
||
# Retry npm ci up to 3 times on failure
|
||
for i in 1 2 3; do
|
||
if npm ci; then
|
||
break
|
||
else
|
||
if [ $i -eq 3 ]; then
|
||
echo "npm ci failed after 3 attempts"
|
||
exit 1
|
||
fi
|
||
echo "npm ci attempt $i failed, retrying in 10 seconds..."
|
||
sleep 10
|
||
fi
|
||
done
|
||
npm install --force @rollup/rollup-darwin-arm64
|
||
npm install dmg-license
|
||
|
||
- name: Check for Code Signing Certificates
|
||
id: check_certs
|
||
run: |
|
||
if [ -n "${{ secrets.MAC_BUILD_CERTIFICATE_BASE64 }}" ] && [ -n "${{ secrets.MAC_P12_PASSWORD }}" ]; then
|
||
echo "has_certs=true" >> $GITHUB_OUTPUT
|
||
else
|
||
echo "has_certs=false" >> $GITHUB_OUTPUT
|
||
echo "⚠️ Code signing certificates not configured. MAS build will be unsigned."
|
||
fi
|
||
|
||
- name: Import Code Signing Certificates
|
||
if: steps.check_certs.outputs.has_certs == 'true'
|
||
env:
|
||
MAC_BUILD_CERTIFICATE_BASE64: ${{ secrets.MAC_BUILD_CERTIFICATE_BASE64 }}
|
||
MAC_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.MAC_INSTALLER_CERTIFICATE_BASE64 }}
|
||
MAC_P12_PASSWORD: ${{ secrets.MAC_P12_PASSWORD }}
|
||
MAC_KEYCHAIN_PASSWORD: ${{ secrets.MAC_KEYCHAIN_PASSWORD }}
|
||
run: |
|
||
APP_CERT_PATH=$RUNNER_TEMP/app_certificate.p12
|
||
INSTALLER_CERT_PATH=$RUNNER_TEMP/installer_certificate.p12
|
||
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
|
||
|
||
# Decode certificates
|
||
echo -n "$MAC_BUILD_CERTIFICATE_BASE64" | base64 --decode -o $APP_CERT_PATH
|
||
|
||
if [ -n "$MAC_INSTALLER_CERTIFICATE_BASE64" ]; then
|
||
echo "Decoding installer certificate..."
|
||
echo -n "$MAC_INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $INSTALLER_CERT_PATH
|
||
else
|
||
echo "⚠️ MAC_INSTALLER_CERTIFICATE_BASE64 is empty"
|
||
fi
|
||
|
||
# Create and configure keychain
|
||
security create-keychain -p "$MAC_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||
security unlock-keychain -p "$MAC_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||
|
||
# Import application certificate
|
||
echo "Importing application certificate..."
|
||
security import $APP_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||
|
||
# Import installer certificate if it exists
|
||
if [ -f "$INSTALLER_CERT_PATH" ]; then
|
||
echo "Importing installer certificate..."
|
||
security import $INSTALLER_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||
else
|
||
echo "⚠️ Installer certificate file not found, skipping import"
|
||
fi
|
||
|
||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||
|
||
echo "Imported certificates:"
|
||
security find-identity -v -p codesigning $KEYCHAIN_PATH
|
||
|
||
- name: Build macOS App Store Package
|
||
if: steps.check_certs.outputs.has_certs == 'true'
|
||
env:
|
||
ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES: true
|
||
run: |
|
||
# Get current version for display
|
||
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
||
BUILD_VERSION="${{ github.run_number }}"
|
||
|
||
echo "✅ Package version: $CURRENT_VERSION (unchanged)"
|
||
echo "✅ Build number for Apple: $BUILD_VERSION"
|
||
|
||
# Build MAS with custom buildVersion
|
||
npm run build && npx electron-builder --mac mas --universal --config.buildVersion="$BUILD_VERSION"
|
||
|
||
- name: Clean up MAS keychain before DMG build
|
||
if: steps.check_certs.outputs.has_certs == 'true'
|
||
run: |
|
||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true
|
||
echo "Cleaned up MAS keychain"
|
||
|
||
- name: Check for Developer ID Certificates
|
||
id: check_dev_id_certs
|
||
run: |
|
||
if [ -n "${{ secrets.DEVELOPER_ID_CERTIFICATE_BASE64 }}" ] && [ -n "${{ secrets.DEVELOPER_ID_P12_PASSWORD }}" ]; then
|
||
echo "has_dev_id_certs=true" >> $GITHUB_OUTPUT
|
||
echo "✅ Developer ID certificates configured for DMG signing"
|
||
else
|
||
echo "has_dev_id_certs=false" >> $GITHUB_OUTPUT
|
||
echo "⚠️ Developer ID certificates not configured. DMG will be unsigned."
|
||
echo "Add DEVELOPER_ID_CERTIFICATE_BASE64 and DEVELOPER_ID_P12_PASSWORD secrets to enable DMG signing."
|
||
fi
|
||
|
||
- name: Import Developer ID Certificates
|
||
if: steps.check_dev_id_certs.outputs.has_dev_id_certs == 'true'
|
||
env:
|
||
DEVELOPER_ID_CERTIFICATE_BASE64: ${{ secrets.DEVELOPER_ID_CERTIFICATE_BASE64 }}
|
||
DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64: ${{ secrets.DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64 }}
|
||
DEVELOPER_ID_P12_PASSWORD: ${{ secrets.DEVELOPER_ID_P12_PASSWORD }}
|
||
MAC_KEYCHAIN_PASSWORD: ${{ secrets.MAC_KEYCHAIN_PASSWORD }}
|
||
run: |
|
||
DEV_CERT_PATH=$RUNNER_TEMP/dev_certificate.p12
|
||
DEV_INSTALLER_CERT_PATH=$RUNNER_TEMP/dev_installer_certificate.p12
|
||
KEYCHAIN_PATH=$RUNNER_TEMP/dev-signing.keychain-db
|
||
|
||
# Decode Developer ID certificate
|
||
echo -n "$DEVELOPER_ID_CERTIFICATE_BASE64" | base64 --decode -o $DEV_CERT_PATH
|
||
|
||
if [ -n "$DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64" ]; then
|
||
echo "Decoding Developer ID installer certificate..."
|
||
echo -n "$DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $DEV_INSTALLER_CERT_PATH
|
||
else
|
||
echo "⚠️ DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64 is empty (optional)"
|
||
fi
|
||
|
||
# Create and configure keychain
|
||
security create-keychain -p "$MAC_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
|
||
security unlock-keychain -p "$MAC_KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
|
||
|
||
# Import Developer ID Application certificate
|
||
echo "Importing Developer ID Application certificate..."
|
||
security import $DEV_CERT_PATH -P "$DEVELOPER_ID_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||
|
||
# Import Developer ID Installer certificate if it exists
|
||
if [ -f "$DEV_INSTALLER_CERT_PATH" ]; then
|
||
echo "Importing Developer ID Installer certificate..."
|
||
security import $DEV_INSTALLER_CERT_PATH -P "$DEVELOPER_ID_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
||
fi
|
||
|
||
security list-keychain -d user -s $KEYCHAIN_PATH
|
||
|
||
echo "Imported Developer ID certificates:"
|
||
security find-identity -v -p codesigning $KEYCHAIN_PATH
|
||
|
||
- name: Build macOS DMG
|
||
env:
|
||
ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES: true
|
||
APPLE_ID: ${{ secrets.APPLE_ID }}
|
||
APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
|
||
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
|
||
run: |
|
||
# Build DMG without running npm run build again (already built above or skip if no certs)
|
||
if [ "${{ steps.check_certs.outputs.has_certs }}" == "true" ]; then
|
||
# Frontend already built, just package DMG
|
||
npx electron-builder --mac dmg --universal --x64 --arm64 --publish never
|
||
else
|
||
# No certs, need to build frontend first
|
||
npm run build && npx electron-builder --mac dmg --universal --x64 --arm64 --publish never
|
||
fi
|
||
|
||
- name: List release directory
|
||
if: steps.check_certs.outputs.has_certs == 'true'
|
||
run: |
|
||
echo "Contents of release directory:"
|
||
ls -R release/ || echo "Release directory not found"
|
||
|
||
- name: Upload macOS MAS PKG
|
||
if: steps.check_certs.outputs.has_certs == 'true' && hashFiles('release/*_*_*_mas.pkg') != '' && (github.event.inputs.artifact_destination == 'file' || github.event.inputs.artifact_destination == 'release' || github.event.inputs.artifact_destination == 'submit')
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: termix_macos_mas
|
||
path: release/*_*_*_mas.pkg
|
||
retention-days: 30
|
||
if-no-files-found: warn
|
||
|
||
- name: Upload macOS Universal DMG
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_universal_*_dmg.dmg') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_macos_universal_dmg
|
||
path: release/*_universal_*_dmg.dmg
|
||
retention-days: 30
|
||
|
||
- name: Upload macOS x64 DMG
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_x64_*_dmg.dmg') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_macos_x64_dmg
|
||
path: release/*_x64_*_dmg.dmg
|
||
retention-days: 30
|
||
|
||
- name: Upload macOS arm64 DMG
|
||
uses: actions/upload-artifact@v4
|
||
if: hashFiles('release/*_arm64_*_dmg.dmg') != '' && github.event.inputs.artifact_destination != 'none'
|
||
with:
|
||
name: termix_macos_arm64_dmg
|
||
path: release/*_arm64_*_dmg.dmg
|
||
retention-days: 30
|
||
|
||
- name: Check for App Store Connect API credentials
|
||
if: steps.check_certs.outputs.has_certs == 'true'
|
||
id: check_asc_creds
|
||
run: |
|
||
if [ -n "${{ secrets.APPLE_KEY_ID }}" ] && [ -n "${{ secrets.APPLE_ISSUER_ID }}" ] && [ -n "${{ secrets.APPLE_KEY_CONTENT }}" ]; then
|
||
echo "has_credentials=true" >> $GITHUB_OUTPUT
|
||
if [ "${{ github.event.inputs.artifact_destination }}" == "submit" ]; then
|
||
echo "✅ App Store Connect API credentials found. Will deploy to TestFlight."
|
||
else
|
||
echo "ℹ️ App Store Connect API credentials found, but store submission is disabled."
|
||
fi
|
||
else
|
||
echo "has_credentials=false" >> $GITHUB_OUTPUT
|
||
echo "⚠️ App Store Connect API credentials not configured. Skipping deployment."
|
||
echo "Add APPLE_KEY_ID, APPLE_ISSUER_ID, and APPLE_KEY_CONTENT secrets to enable automatic deployment."
|
||
fi
|
||
|
||
- name: Setup Ruby for Fastlane
|
||
if: steps.check_asc_creds.outputs.has_credentials == 'true' && github.event.inputs.artifact_destination == 'submit'
|
||
uses: ruby/setup-ruby@v1
|
||
with:
|
||
ruby-version: '3.2'
|
||
bundler-cache: false
|
||
|
||
- name: Install Fastlane
|
||
if: steps.check_asc_creds.outputs.has_credentials == 'true' && github.event.inputs.artifact_destination == 'submit'
|
||
run: |
|
||
gem install fastlane -N
|
||
fastlane --version
|
||
|
||
- name: Deploy to App Store Connect (TestFlight)
|
||
if: steps.check_asc_creds.outputs.has_credentials == 'true' && github.event.inputs.artifact_destination == 'submit'
|
||
run: |
|
||
PKG_FILE=$(find release -name "*.pkg" -type f | head -n 1)
|
||
if [ -z "$PKG_FILE" ]; then
|
||
echo "Error: No .pkg file found in release directory"
|
||
exit 1
|
||
fi
|
||
echo "Found package: $PKG_FILE"
|
||
|
||
# Create API key file
|
||
mkdir -p ~/private_keys
|
||
echo "${{ secrets.APPLE_KEY_CONTENT }}" | base64 --decode > ~/private_keys/AuthKey_${{ secrets.APPLE_KEY_ID }}.p8
|
||
|
||
# Upload to App Store Connect using xcrun altool
|
||
xcrun altool --upload-app -f "$PKG_FILE" \
|
||
--type macos \
|
||
--apiKey "${{ secrets.APPLE_KEY_ID }}" \
|
||
--apiIssuer "${{ secrets.APPLE_ISSUER_ID }}"
|
||
|
||
echo "✅ Upload complete! Build will appear in App Store Connect after processing (10-30 minutes)"
|
||
continue-on-error: true
|
||
|
||
- name: Clean up keychains
|
||
if: always()
|
||
run: |
|
||
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true
|
||
security delete-keychain $RUNNER_TEMP/dev-signing.keychain-db || true
|
||
|
||
submit-to-chocolatey:
|
||
runs-on: windows-latest
|
||
if: github.event.inputs.artifact_destination == 'submit'
|
||
needs: [build-windows]
|
||
permissions:
|
||
contents: read
|
||
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 1
|
||
|
||
- name: Get version from package.json
|
||
id: package-version
|
||
run: |
|
||
$VERSION = (Get-Content package.json | ConvertFrom-Json).version
|
||
echo "version=$VERSION" >> $env:GITHUB_OUTPUT
|
||
echo "Building Chocolatey package for version: $VERSION"
|
||
|
||
- name: Download Windows x64 MSI artifact
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: termix_windows_x64_msi
|
||
path: artifact
|
||
|
||
- name: Get MSI file info
|
||
id: msi-info
|
||
run: |
|
||
$VERSION = "${{ steps.package-version.outputs.version }}"
|
||
$MSI_FILE = Get-ChildItem -Path artifact -Filter "*.msi" | Select-Object -First 1
|
||
$MSI_NAME = $MSI_FILE.Name
|
||
$CHECKSUM = (Get-FileHash -Path $MSI_FILE.FullName -Algorithm SHA256).Hash
|
||
|
||
echo "msi_name=$MSI_NAME" >> $env:GITHUB_OUTPUT
|
||
echo "checksum=$CHECKSUM" >> $env:GITHUB_OUTPUT
|
||
echo "MSI File: $MSI_NAME"
|
||
echo "SHA256: $CHECKSUM"
|
||
|
||
- name: Prepare Chocolatey package
|
||
run: |
|
||
$VERSION = "${{ steps.package-version.outputs.version }}"
|
||
$CHECKSUM = "${{ steps.msi-info.outputs.checksum }}"
|
||
$MSI_NAME = "${{ steps.msi-info.outputs.msi_name }}"
|
||
|
||
# Construct the download URL with the actual release tag format
|
||
$DOWNLOAD_URL = "https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$MSI_NAME"
|
||
|
||
# Copy chocolatey files to build directory
|
||
New-Item -ItemType Directory -Force -Path "choco-build"
|
||
Copy-Item -Path "chocolatey\*" -Destination "choco-build" -Recurse -Force
|
||
|
||
# Update chocolateyinstall.ps1 with actual values
|
||
$installScript = Get-Content "choco-build\tools\chocolateyinstall.ps1" -Raw -Encoding UTF8
|
||
$installScript = $installScript -replace 'DOWNLOAD_URL_PLACEHOLDER', $DOWNLOAD_URL
|
||
$installScript = $installScript -replace 'CHECKSUM_PLACEHOLDER', $CHECKSUM
|
||
[System.IO.File]::WriteAllText("$PWD\choco-build\tools\chocolateyinstall.ps1", $installScript, [System.Text.UTF8Encoding]::new($false))
|
||
|
||
# Update nuspec with version (preserve UTF-8 encoding without BOM)
|
||
$nuspec = Get-Content "choco-build\termix-ssh.nuspec" -Raw -Encoding UTF8
|
||
$nuspec = $nuspec -replace 'VERSION_PLACEHOLDER', $VERSION
|
||
[System.IO.File]::WriteAllText("$PWD\choco-build\termix-ssh.nuspec", $nuspec, [System.Text.UTF8Encoding]::new($false))
|
||
|
||
echo "Chocolatey package prepared for version $VERSION"
|
||
echo "Download URL: $DOWNLOAD_URL"
|
||
|
||
# Verify the nuspec is valid
|
||
echo ""
|
||
echo "Verifying nuspec content:"
|
||
Get-Content "choco-build\termix-ssh.nuspec" -Head 10
|
||
echo ""
|
||
|
||
- name: Install Chocolatey
|
||
run: |
|
||
Set-ExecutionPolicy Bypass -Scope Process -Force
|
||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
|
||
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
||
|
||
- name: Pack Chocolatey package
|
||
run: |
|
||
cd choco-build
|
||
echo "Packing Chocolatey package..."
|
||
choco pack termix-ssh.nuspec
|
||
|
||
if ($LASTEXITCODE -ne 0) {
|
||
echo "❌ Failed to pack Chocolatey package"
|
||
exit 1
|
||
}
|
||
|
||
echo ""
|
||
echo "✅ Package created successfully"
|
||
echo "Package contents:"
|
||
Get-ChildItem *.nupkg | ForEach-Object { echo $_.Name }
|
||
|
||
- name: Check for Chocolatey API Key
|
||
id: check_choco_key
|
||
run: |
|
||
if ("${{ secrets.CHOCOLATEY_API_KEY }}" -ne "") {
|
||
echo "has_key=true" >> $env:GITHUB_OUTPUT
|
||
echo "✅ Chocolatey API key found. Will push to Chocolatey."
|
||
} else {
|
||
echo "has_key=false" >> $env:GITHUB_OUTPUT
|
||
echo "⚠️ Chocolatey API key not configured. Package will be created but not pushed."
|
||
echo "Add CHOCOLATEY_API_KEY secret to enable automatic submission."
|
||
}
|
||
|
||
- name: Push to Chocolatey
|
||
if: steps.check_choco_key.outputs.has_key == 'true'
|
||
run: |
|
||
$VERSION = "${{ steps.package-version.outputs.version }}"
|
||
cd choco-build
|
||
choco apikey --key "${{ secrets.CHOCOLATEY_API_KEY }}" --source https://push.chocolatey.org/
|
||
|
||
try {
|
||
choco push "termix-ssh.$VERSION.nupkg" --source https://push.chocolatey.org/
|
||
if ($LASTEXITCODE -eq 0) {
|
||
echo ""
|
||
echo "✅ Package pushed to Chocolatey successfully!"
|
||
echo "View at: https://community.chocolatey.org/packages/termix-ssh/$VERSION"
|
||
} else {
|
||
throw "Chocolatey push failed with exit code $LASTEXITCODE"
|
||
}
|
||
} catch {
|
||
echo ""
|
||
echo "❌ Failed to push to Chocolatey"
|
||
echo ""
|
||
echo "Common reasons:"
|
||
echo "1. Package ID 'termix-ssh' is already owned by another user"
|
||
echo "2. You need to register/claim the package ID first"
|
||
echo "3. API key doesn't have push permissions"
|
||
echo ""
|
||
echo "Solutions:"
|
||
echo "1. Check if package exists: https://community.chocolatey.org/packages/termix-ssh"
|
||
echo "2. If it exists and is yours, contact Chocolatey support to claim it"
|
||
echo "3. Register a new package ID at: https://community.chocolatey.org/"
|
||
echo ""
|
||
echo "The package artifact has been saved for manual submission."
|
||
echo ""
|
||
exit 1
|
||
}
|
||
|
||
- name: Upload Chocolatey package as artifact
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: chocolatey-package
|
||
path: choco-build/*.nupkg
|
||
retention-days: 30
|
||
|
||
submit-to-flatpak:
|
||
runs-on: ubuntu-latest
|
||
if: github.event.inputs.artifact_destination == 'submit'
|
||
needs: [build-linux]
|
||
permissions:
|
||
contents: read
|
||
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 1
|
||
|
||
- name: Get version from package.json
|
||
id: package-version
|
||
run: |
|
||
VERSION=$(node -p "require('./package.json').version")
|
||
RELEASE_DATE=$(date +%Y-%m-%d)
|
||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||
echo "release_date=$RELEASE_DATE" >> $GITHUB_OUTPUT
|
||
echo "Building Flatpak submission for version: $VERSION"
|
||
|
||
- name: Download Linux x64 AppImage artifact
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: termix_linux_x64_appimage
|
||
path: artifact-x64
|
||
|
||
- name: Download Linux arm64 AppImage artifact
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: termix_linux_arm64_appimage
|
||
path: artifact-arm64
|
||
|
||
- name: Get AppImage file info
|
||
id: appimage-info
|
||
run: |
|
||
VERSION="${{ steps.package-version.outputs.version }}"
|
||
|
||
# x64 AppImage
|
||
APPIMAGE_X64_FILE=$(find artifact-x64 -name "*.AppImage" -type f | head -n 1)
|
||
APPIMAGE_X64_NAME=$(basename "$APPIMAGE_X64_FILE")
|
||
CHECKSUM_X64=$(sha256sum "$APPIMAGE_X64_FILE" | awk '{print $1}')
|
||
|
||
# arm64 AppImage
|
||
APPIMAGE_ARM64_FILE=$(find artifact-arm64 -name "*.AppImage" -type f | head -n 1)
|
||
APPIMAGE_ARM64_NAME=$(basename "$APPIMAGE_ARM64_FILE")
|
||
CHECKSUM_ARM64=$(sha256sum "$APPIMAGE_ARM64_FILE" | awk '{print $1}')
|
||
|
||
echo "appimage_x64_name=$APPIMAGE_X64_NAME" >> $GITHUB_OUTPUT
|
||
echo "checksum_x64=$CHECKSUM_X64" >> $GITHUB_OUTPUT
|
||
echo "appimage_arm64_name=$APPIMAGE_ARM64_NAME" >> $GITHUB_OUTPUT
|
||
echo "checksum_arm64=$CHECKSUM_ARM64" >> $GITHUB_OUTPUT
|
||
|
||
echo "x64 AppImage: $APPIMAGE_X64_NAME"
|
||
echo "x64 SHA256: $CHECKSUM_X64"
|
||
echo "arm64 AppImage: $APPIMAGE_ARM64_NAME"
|
||
echo "arm64 SHA256: $CHECKSUM_ARM64"
|
||
|
||
- name: Install ImageMagick for icon generation
|
||
run: |
|
||
sudo apt-get update
|
||
sudo apt-get install -y imagemagick
|
||
|
||
- name: Prepare Flatpak submission files
|
||
run: |
|
||
VERSION="${{ steps.package-version.outputs.version }}"
|
||
CHECKSUM_X64="${{ steps.appimage-info.outputs.checksum_x64 }}"
|
||
CHECKSUM_ARM64="${{ steps.appimage-info.outputs.checksum_arm64 }}"
|
||
RELEASE_DATE="${{ steps.package-version.outputs.release_date }}"
|
||
APPIMAGE_X64_NAME="${{ steps.appimage-info.outputs.appimage_x64_name }}"
|
||
APPIMAGE_ARM64_NAME="${{ steps.appimage-info.outputs.appimage_arm64_name }}"
|
||
|
||
# Create submission directory
|
||
mkdir -p flatpak-submission
|
||
|
||
# Copy Flatpak files to submission directory
|
||
cp flatpak/com.karmaa.termix.yml flatpak-submission/
|
||
cp flatpak/com.karmaa.termix.desktop flatpak-submission/
|
||
cp flatpak/com.karmaa.termix.metainfo.xml flatpak-submission/
|
||
cp flatpak/flathub.json flatpak-submission/
|
||
|
||
# Copy and prepare icons
|
||
cp public/icon.svg flatpak-submission/com.karmaa.termix.svg
|
||
convert public/icon.png -resize 256x256 flatpak-submission/icon-256.png
|
||
convert public/icon.png -resize 128x128 flatpak-submission/icon-128.png
|
||
|
||
# Update manifest with version and checksums
|
||
sed -i "s/VERSION_PLACEHOLDER/$VERSION/g" flatpak-submission/com.karmaa.termix.yml
|
||
sed -i "s/CHECKSUM_X64_PLACEHOLDER/$CHECKSUM_X64/g" flatpak-submission/com.karmaa.termix.yml
|
||
sed -i "s/CHECKSUM_ARM64_PLACEHOLDER/$CHECKSUM_ARM64/g" flatpak-submission/com.karmaa.termix.yml
|
||
|
||
# Update metainfo with version and date
|
||
sed -i "s/VERSION_PLACEHOLDER/$VERSION/g" flatpak-submission/com.karmaa.termix.metainfo.xml
|
||
sed -i "s/DATE_PLACEHOLDER/$RELEASE_DATE/g" flatpak-submission/com.karmaa.termix.metainfo.xml
|
||
|
||
echo "✅ Flatpak submission files prepared for version $VERSION"
|
||
echo "x64 Download URL: https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$APPIMAGE_X64_NAME"
|
||
echo "arm64 Download URL: https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$APPIMAGE_ARM64_NAME"
|
||
|
||
- name: Create submission instructions
|
||
run: |
|
||
cat > flatpak-submission/SUBMISSION_INSTRUCTIONS.md << 'EOF'
|
||
# Flathub Submission Instructions for Termix
|
||
|
||
## Automatic Submission (Recommended)
|
||
|
||
All files needed for Flathub submission are in this artifact. Follow these steps:
|
||
|
||
1. **Fork the Flathub repository**:
|
||
- Go to https://github.com/flathub/flathub
|
||
- Click "Fork" button
|
||
|
||
2. **Clone your fork**:
|
||
```bash
|
||
git clone https://github.com/YOUR-USERNAME/flathub.git
|
||
cd flathub
|
||
git checkout -b com.karmaa.termix
|
||
```
|
||
|
||
3. **Copy all files from this artifact** to the root of your flathub fork
|
||
|
||
4. **Commit and push**:
|
||
```bash
|
||
git add .
|
||
git commit -m "Add Termix ${{ steps.package-version.outputs.version }}"
|
||
git push origin com.karmaa.termix
|
||
```
|
||
|
||
5. **Create Pull Request**:
|
||
- Go to https://github.com/YOUR-USERNAME/flathub
|
||
- Click "Compare & pull request"
|
||
- Submit PR to flathub/flathub
|
||
|
||
## Files in this submission:
|
||
|
||
- `com.karmaa.termix.yml` - Flatpak manifest
|
||
- `com.karmaa.termix.desktop` - Desktop entry
|
||
- `com.karmaa.termix.metainfo.xml` - AppStream metadata
|
||
- `flathub.json` - Flathub configuration
|
||
- `com.karmaa.termix.svg` - SVG icon
|
||
- `icon-256.png` - 256x256 icon
|
||
- `icon-128.png` - 128x128 icon
|
||
|
||
## Version Information:
|
||
|
||
- Version: ${{ steps.package-version.outputs.version }}
|
||
- Release Date: ${{ steps.package-version.outputs.release_date }}
|
||
- x64 AppImage SHA256: ${{ steps.appimage-info.outputs.checksum_x64 }}
|
||
- arm64 AppImage SHA256: ${{ steps.appimage-info.outputs.checksum_arm64 }}
|
||
|
||
## After Submission:
|
||
|
||
1. Flathub maintainers will review your submission (usually 1-5 days)
|
||
2. They may request changes - be responsive to feedback
|
||
3. Once approved, Termix will be available via: `flatpak install flathub com.karmaa.termix`
|
||
|
||
## Resources:
|
||
|
||
- [Flathub Submission Guidelines](https://docs.flathub.org/docs/for-app-authors/submission)
|
||
- [Flatpak Documentation](https://docs.flatpak.org/)
|
||
EOF
|
||
|
||
echo "✅ Created submission instructions"
|
||
|
||
- name: List submission files
|
||
run: |
|
||
echo "Flatpak submission files:"
|
||
ls -la flatpak-submission/
|
||
|
||
- name: Upload Flatpak submission as artifact
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: flatpak-submission
|
||
path: flatpak-submission/*
|
||
retention-days: 30
|
||
|
||
- name: Display next steps
|
||
run: |
|
||
echo ""
|
||
echo "🎉 Flatpak submission files ready!"
|
||
echo ""
|
||
echo "📦 Download the 'flatpak-submission' artifact and follow SUBMISSION_INSTRUCTIONS.md"
|
||
echo ""
|
||
echo "Quick summary:"
|
||
echo "1. Fork https://github.com/flathub/flathub"
|
||
echo "2. Copy artifact files to your fork"
|
||
echo "3. Create PR to flathub/flathub"
|
||
echo ""
|
||
|
||
submit-to-homebrew:
|
||
runs-on: macos-latest
|
||
if: github.event.inputs.artifact_destination == 'submit'
|
||
needs: [build-macos]
|
||
permissions:
|
||
contents: read
|
||
|
||
steps:
|
||
- name: Checkout repository
|
||
uses: actions/checkout@v5
|
||
with:
|
||
fetch-depth: 1
|
||
|
||
- name: Get version from package.json
|
||
id: package-version
|
||
run: |
|
||
VERSION=$(node -p "require('./package.json').version")
|
||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||
echo "Building Homebrew Cask for version: $VERSION"
|
||
|
||
- name: Download macOS Universal DMG artifact
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
name: termix_macos_universal_dmg
|
||
path: artifact
|
||
|
||
- name: Get DMG file info
|
||
id: dmg-info
|
||
run: |
|
||
VERSION="${{ steps.package-version.outputs.version }}"
|
||
DMG_FILE=$(find artifact -name "*.dmg" -type f | head -n 1)
|
||
DMG_NAME=$(basename "$DMG_FILE")
|
||
CHECKSUM=$(shasum -a 256 "$DMG_FILE" | awk '{print $1}')
|
||
|
||
echo "dmg_name=$DMG_NAME" >> $GITHUB_OUTPUT
|
||
echo "checksum=$CHECKSUM" >> $GITHUB_OUTPUT
|
||
echo "DMG File: $DMG_NAME"
|
||
echo "SHA256: $CHECKSUM"
|
||
|
||
- name: Prepare Homebrew submission files
|
||
run: |
|
||
VERSION="${{ steps.package-version.outputs.version }}"
|
||
CHECKSUM="${{ steps.dmg-info.outputs.checksum }}"
|
||
DMG_NAME="${{ steps.dmg-info.outputs.dmg_name }}"
|
||
|
||
# Create submission directory
|
||
mkdir -p homebrew-submission/Casks/t
|
||
|
||
# Copy Homebrew cask file
|
||
cp homebrew/termix.rb homebrew-submission/Casks/t/termix.rb
|
||
cp homebrew/README.md homebrew-submission/
|
||
|
||
# Update cask with version and checksum
|
||
sed -i '' "s/VERSION_PLACEHOLDER/$VERSION/g" homebrew-submission/Casks/t/termix.rb
|
||
sed -i '' "s/CHECKSUM_PLACEHOLDER/$CHECKSUM/g" homebrew-submission/Casks/t/termix.rb
|
||
|
||
echo "✅ Homebrew Cask prepared for version $VERSION"
|
||
echo "Download URL: https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$DMG_NAME"
|
||
|
||
- name: Verify Cask syntax
|
||
run: |
|
||
# Install Homebrew if not present (should be on macos-latest)
|
||
if ! command -v brew &> /dev/null; then
|
||
echo "Installing Homebrew..."
|
||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
||
fi
|
||
|
||
# Basic syntax check
|
||
ruby -c homebrew-submission/Casks/t/termix.rb
|
||
echo "✅ Cask syntax is valid"
|
||
|
||
- name: Create submission instructions
|
||
run: |
|
||
cat > homebrew-submission/SUBMISSION_INSTRUCTIONS.md << 'EOF'
|
||
# Homebrew Cask Submission Instructions for Termix
|
||
|
||
## Option 1: Submit to Official Homebrew Cask (Recommended)
|
||
|
||
### Prerequisites
|
||
- macOS with Homebrew installed
|
||
- GitHub account
|
||
|
||
### Steps
|
||
|
||
1. **Fork the Homebrew Cask repository**:
|
||
- Go to https://github.com/Homebrew/homebrew-cask
|
||
- Click "Fork" button
|
||
|
||
2. **Clone your fork**:
|
||
```bash
|
||
git clone https://github.com/YOUR-USERNAME/homebrew-cask.git
|
||
cd homebrew-cask
|
||
git checkout -b termix
|
||
```
|
||
|
||
3. **Copy the cask file**:
|
||
- Copy `Casks/t/termix.rb` from this artifact to your fork at `Casks/t/termix.rb`
|
||
- Note: Casks are organized by first letter in subdirectories
|
||
|
||
4. **Test the cask locally**:
|
||
```bash
|
||
brew install --cask ./Casks/t/termix.rb
|
||
brew uninstall --cask termix
|
||
```
|
||
|
||
5. **Run audit checks**:
|
||
```bash
|
||
brew audit --cask --online ./Casks/t/termix.rb
|
||
brew style ./Casks/t/termix.rb
|
||
```
|
||
|
||
6. **Commit and push**:
|
||
```bash
|
||
git add Casks/t/termix.rb
|
||
git commit -m "Add Termix ${{ steps.package-version.outputs.version }}"
|
||
git push origin termix
|
||
```
|
||
|
||
7. **Create Pull Request**:
|
||
- Go to https://github.com/YOUR-USERNAME/homebrew-cask
|
||
- Click "Compare & pull request"
|
||
- Fill in the PR template
|
||
- Submit to Homebrew/homebrew-cask
|
||
|
||
### PR Requirements
|
||
|
||
Your PR should include:
|
||
- Clear commit message: "Add Termix X.Y.Z" or "Update Termix to X.Y.Z"
|
||
- All audit checks passing
|
||
- Working download URL
|
||
- Valid SHA256 checksum
|
||
|
||
## Option 2: Create Your Own Tap (Alternative)
|
||
|
||
If you want more control and faster updates:
|
||
|
||
1. **Create a tap repository**:
|
||
- Create repo: `Termix-SSH/homebrew-termix`
|
||
- Add `Casks/termix.rb` to the repo
|
||
|
||
2. **Users install with**:
|
||
```bash
|
||
brew tap termix-ssh/termix
|
||
brew install --cask termix
|
||
```
|
||
|
||
### Advantages of Custom Tap
|
||
- No approval process
|
||
- Instant updates
|
||
- Full control
|
||
- Can include beta versions
|
||
|
||
### Disadvantages
|
||
- Less discoverable
|
||
- Users must add tap first
|
||
- You maintain it yourself
|
||
|
||
## Files in this submission:
|
||
|
||
- `Casks/t/termix.rb` - Homebrew Cask formula
|
||
- `README.md` - Detailed documentation
|
||
- `SUBMISSION_INSTRUCTIONS.md` - This file
|
||
|
||
## Version Information:
|
||
|
||
- Version: ${{ steps.package-version.outputs.version }}
|
||
- DMG SHA256: ${{ steps.dmg-info.outputs.checksum }}
|
||
- DMG URL: https://github.com/Termix-SSH/Termix/releases/download/release-${{ steps.package-version.outputs.version }}-tag/${{ steps.dmg-info.outputs.dmg_name }}
|
||
|
||
## After Submission:
|
||
|
||
### Official Homebrew Cask:
|
||
1. Maintainers will review (usually 24-48 hours)
|
||
2. May request changes or fixes
|
||
3. Once merged, users can install with: `brew install --cask termix`
|
||
4. Homebrew bot will auto-update for future releases
|
||
|
||
### Custom Tap:
|
||
1. Push to your tap repository
|
||
2. Immediately available to users
|
||
3. Update the cask file for each new release
|
||
|
||
## Resources:
|
||
|
||
- [Homebrew Cask Documentation](https://docs.brew.sh/Cask-Cookbook)
|
||
- [Acceptable Casks](https://docs.brew.sh/Acceptable-Casks)
|
||
- [How to Open a PR](https://docs.brew.sh/How-To-Open-a-Homebrew-Pull-Request)
|
||
EOF
|
||
|
||
echo "✅ Created submission instructions"
|
||
|
||
- name: List submission files
|
||
run: |
|
||
echo "Homebrew submission files:"
|
||
find homebrew-submission -type f
|
||
|
||
- name: Upload Homebrew submission as artifact
|
||
uses: actions/upload-artifact@v4
|
||
with:
|
||
name: homebrew-submission
|
||
path: homebrew-submission/*
|
||
retention-days: 30
|
||
|
||
- name: Display next steps
|
||
run: |
|
||
echo ""
|
||
echo "🍺 Homebrew Cask ready!"
|
||
echo ""
|
||
echo "📦 Download the 'homebrew-submission' artifact and follow SUBMISSION_INSTRUCTIONS.md"
|
||
echo ""
|
||
echo "Quick summary:"
|
||
echo "Option 1 (Recommended): Fork https://github.com/Homebrew/homebrew-cask and submit PR"
|
||
echo "Option 2 (Alternative): Create your own tap at Termix-SSH/homebrew-termix"
|
||
echo ""
|
||
|
||
upload-to-release:
|
||
runs-on: blacksmith-4vcpu-ubuntu-2404
|
||
if: github.event.inputs.artifact_destination == 'release'
|
||
needs: [build-windows, build-linux, build-macos]
|
||
permissions:
|
||
contents: write
|
||
|
||
steps:
|
||
- name: Download all artifacts
|
||
uses: actions/download-artifact@v4
|
||
with:
|
||
path: artifacts
|
||
|
||
- name: Get latest release
|
||
id: get_release
|
||
run: |
|
||
echo "Fetching latest release from ${{ github.repository }}..."
|
||
LATEST_RELEASE=$(gh release list --repo ${{ github.repository }} --limit 1 --json tagName,name,isLatest -q '.[0]')
|
||
|
||
if [ -z "$LATEST_RELEASE" ]; then
|
||
echo "ERROR: No releases found in ${{ github.repository }}"
|
||
exit 1
|
||
fi
|
||
|
||
RELEASE_TAG=$(echo "$LATEST_RELEASE" | jq -r '.tagName')
|
||
RELEASE_NAME=$(echo "$LATEST_RELEASE" | jq -r '.name')
|
||
|
||
echo "tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
|
||
echo "name=$RELEASE_NAME" >> $GITHUB_OUTPUT
|
||
echo "Latest release: $RELEASE_NAME ($RELEASE_TAG)"
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|
||
|
||
- name: Display artifact structure
|
||
run: |
|
||
echo "Artifact structure:"
|
||
ls -R artifacts/
|
||
|
||
- name: Upload artifacts to latest release
|
||
run: |
|
||
RELEASE_TAG="${{ steps.get_release.outputs.tag }}"
|
||
echo "Uploading artifacts to release: $RELEASE_TAG"
|
||
echo ""
|
||
|
||
cd artifacts
|
||
for dir in */; do
|
||
echo "Processing directory: $dir"
|
||
cd "$dir"
|
||
for file in *; do
|
||
if [ -f "$file" ]; then
|
||
echo "Uploading: $file"
|
||
gh release upload "$RELEASE_TAG" "$file" --repo ${{ github.repository }} --clobber
|
||
echo "✓ $file uploaded successfully"
|
||
fi
|
||
done
|
||
cd ..
|
||
done
|
||
|
||
echo ""
|
||
echo "All artifacts uploaded to: https://github.com/${{ github.repository }}/releases/tag/$RELEASE_TAG"
|
||
env:
|
||
GH_TOKEN: ${{ github.token }}
|