* fix select edit host but not update view (#438) * fix: Checksum issue with chocolatey * fix: Remove homebrew old stuff * Add Korean translation (#439) Co-authored-by: 송준우 <2484@coreit.co.kr> * feat: Automate flatpak * fix: Add imagemagik to electron builder to resolve build error * fix: Build error with runtime repo flag * fix: Flatpak runtime error and install freedesktop ver warning * fix: Flatpak runtime error and install freedesktop ver warning * feat: Re-add homebrew cask and move scripts to backend * fix: No sandbox flag issue * fix: Change name for electron macos cask output * fix: Sandbox error with Linux * fix: Remove comming soon for app stores in readme * Adding Comment at the end of the public_key on the host on deploy (#440) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * -Add New Interface for Credential DB -Add Credential Name as a comment into the server authorized_key file --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> * Sudo auto fill password (#441) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * Feature Sudo password auto-fill; * Fix locale json shema; --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> * Added Italian Language; (#445) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * Added Italian Language; --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> * Auto collapse snippet folders (#448) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * feat: Add collapsable snippets (customizable in user profile) * Translations (#447) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * Added Italian Language; * Fix translations; Removed duplicate keys, synchronised other languages using English as the source, translated added keys, fixed inaccurate translations. --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> * Remove PTY-level keepalive (#449) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * Remove PTY-level keepalive to prevent unwanted terminal output; use SSH-level keepalive instead --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> * feat: Seperate server stats and tunnel management (improved both UI's) then started initial docker implementation * fix: finalize adding docker to db * feat: Add docker management support (local squash) * Fix RBAC role system bugs and improve UX (#446) * Fix RBAC role system bugs and improve UX - Fix user list dropdown selection in host sharing - Fix role sharing permissions to include role-based access - Fix translation template interpolation for success messages - Standardize system roles to admin and user only - Auto-assign user role to new registrations - Remove blocking confirmation dialogs in modal contexts - Add missing i18n keys for common actions - Fix button type to prevent unintended form submissions * Enhance RBAC system with UI improvements and security fixes - Move role assignment to Users tab with per-user role management - Protect system roles (admin/user) from editing and manual assignment - Simplify permission system: remove Use level, keep View and Manage - Hide Update button and Sharing tab for view-only/shared hosts - Prevent users from sharing hosts with themselves - Unify table and modal styling across admin panels - Auto-assign system roles on user registration - Add permission metadata to host interface * Add empty state message for role assignment - Display helpful message when no custom roles available - Clarify that system roles are auto-assigned - Add noCustomRolesToAssign translation in English and Chinese * fix: Prevent credential sharing errors for shared hosts - Skip credential resolution for shared hosts with credential authentication to prevent decryption errors (credentials are encrypted per-user) - Add warning alert in sharing tab when host uses credential authentication - Inform users that shared users cannot connect to credential-based hosts - Add translations for credential sharing warning (EN/ZH) This prevents authentication failures when sharing hosts configured with credential authentication while maintaining security by keeping credentials isolated per user. * feat: Improve rbac UI and fixes some bugs --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> Co-authored-by: LukeGus <bugattiguy527@gmail.com> * SOCKS5 support (#452) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * SOCKS5 support Adding single and chain socks5 proxy support * fix: cleanup files --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> Co-authored-by: LukeGus <bugattiguy527@gmail.com> * Notes and Expiry fields add (#453) * Add termix.rb Cask file * Update Termix to version 1.9.0 with new checksum * Update README to remove 'coming soon' notes * Notes and Expiry add * fix: cleanup files --------- Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> Co-authored-by: LukeGus <bugattiguy527@gmail.com> * fix: ssh host types * fix: sudo incorrect styling and remove expiration date * feat: add sudo password and add diagonal bg's * fix: snippet running on enter key * fix: base64 decoding * fix: improve server stats / rbac * fix: wrap ssh host json export in hosts array * feat: auto trim host inputs, fix file manager jump hosts, dashboard prevent duplicates, file manager terminal not size updating, improve left sidebar sorting, hide/show tags, add apperance user profile tab, add new host manager tabs. * feat: improve terminal connection speed * fix: sqlite constriant errors and support non-root user (nginx perm issue) * feat: add beta syntax highlighing to terminal * feat: update imports and improve admin settings user management * chore: update translations * chore: update translations * feat: Complete light mode implementation with semantic theme system (#450) - Add comprehensive light/dark mode CSS variables with semantic naming - Implement theme-aware scrollbars using CSS variables - Add light mode backgrounds: --bg-base, --bg-elevated, --bg-surface, etc. - Add theme-aware borders: --border-base, --border-panel, --border-subtle - Add semantic text colors: --foreground-secondary, --foreground-subtle - Convert oklch colors to hex for better compatibility - Add theme awareness to CodeMirror editors - Update dark mode colors for consistency (background, sidebar, card, muted, input) - Add Tailwind color mappings for semantic classes Co-authored-by: Luke Gustafson <88517757+LukeGus@users.noreply.github.com> * fix: syntax errors * chore: updating/match themes and split admin settings * feat: add translation workflow and remove old translation.json * fix: translation workflow error * fix: translation workflow error * feat: improve translation system and update workflow * fix: wrong path for translations * fix: change translation to flat files * fix: gh rule error * chore: auto-translate to multiple languages (#458) * chore: improve organization and made a few styling changes in host manager * feat: improve terminal stability and split out the host manager * fix: add unnversiioned files * chore: migrate all to use the new theme system * fix: wrong animation line colors * fix: rbac implementation general issues (local squash) * fix: remove unneeded files * feat: add 10 new langs * chore: update gitnore * chore: auto-translate to multiple languages (#459) * fix: improve tunnel system * fix: properly split tabs, still need to fix up the host manager * chore: cleanup files (possible RC) * feat: add norwegian * chore: auto-translate to multiple languages (#461) * fix: small qol fixes and began readme update * fix: run cleanup script * feat: add docker docs button * feat: general bug fixes and readme updates * fix: translations * chore: auto-translate to multiple languages (#462) * fix: cleanup files * fix: test new translation issue and add better server-stats support * fix: fix translate error * chore: auto-translate to multiple languages (#463) * fix: fix translate mismatching text * chore: auto-translate to multiple languages (#465) * fix: fix translate mismatching text * fix: fix translate mismatching text * chore: auto-translate to multiple languages (#466) * fix: fix translate mismatching text * fix: fix translate mismatching text * fix: fix translate mismatching text * chore: auto-translate to multiple languages (#467) * fix: fix translate mismatching text * chore: auto-translate to multiple languages (#468) * feat: add to readme, a few qol changes, and improve server stats in general * chore: auto-translate to multiple languages (#469) * feat: turned disk uage into graph and fixed issue with termina console * fix: electron build error and hide icons when shared * chore: run clean * fix: general server stats issues, file manager decoding, ui qol * fix: add dashboard line breaks * fix: docker console error * fix: docker console not loading and mismatched stripped background for electron * fix: docker console not loading * chore: docker console not loading in docker * chore: translate readme to chinese * chore: match package lock to package json * chore: nginx config issue for dokcer console * chore: auto-translate to multiple languages (#470) --------- Co-authored-by: Tran Trung Kien <kientt13.7@gmail.com> Co-authored-by: junu <bigdwarf_@naver.com> Co-authored-by: 송준우 <2484@coreit.co.kr> Co-authored-by: SlimGary <trash.slim@gmail.com> Co-authored-by: Nunzio Marfè <nunzio.marfe@protonmail.com> Co-authored-by: Wesley Reid <starhound@lostsouls.org> Co-authored-by: ZacharyZcR <zacharyzcr1984@gmail.com> Co-authored-by: Denis <38875137+Medvedinca@users.noreply.github.com> Co-authored-by: Peet McKinney <68706879+PeetMcK@users.noreply.github.com>
999 lines
38 KiB
YAML
999 lines
38 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 == '') && github.event.inputs.artifact_destination != 'submit'
|
|
permissions:
|
|
contents: write
|
|
|
|
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: |
|
|
$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
|
|
}
|
|
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
|
|
|
|
- name: Build Windows (All Architectures)
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: npm run build && npx electron-builder --win --x64 --ia32
|
|
|
|
- name: Upload Windows x64 NSIS Installer
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_windows_x64_nsis.exe') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_windows_x64_nsis
|
|
path: release/termix_windows_x64_nsis.exe
|
|
retention-days: 30
|
|
|
|
- name: Upload Windows ia32 NSIS Installer
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_windows_ia32_nsis.exe') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_windows_ia32_nsis
|
|
path: release/termix_windows_ia32_nsis.exe
|
|
retention-days: 30
|
|
|
|
- name: Upload Windows x64 MSI Installer
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_windows_x64_msi.msi') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_windows_x64_msi
|
|
path: release/termix_windows_x64_msi.msi
|
|
retention-days: 30
|
|
|
|
- name: Upload Windows ia32 MSI Installer
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_windows_ia32_msi.msi') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_windows_ia32_msi
|
|
path: release/termix_windows_ia32_msi.msi
|
|
retention-days: 30
|
|
|
|
- name: Create Windows x64 Portable zip
|
|
if: hashFiles('release/win-unpacked/*') != ''
|
|
run: |
|
|
Compress-Archive -Path "release\win-unpacked\*" -DestinationPath "termix_windows_x64_portable.zip"
|
|
|
|
- name: Create Windows ia32 Portable zip
|
|
if: hashFiles('release/win-ia32-unpacked/*') != ''
|
|
run: |
|
|
Compress-Archive -Path "release\win-ia32-unpacked\*" -DestinationPath "termix_windows_ia32_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 == '') && github.event.inputs.artifact_destination != 'submit'
|
|
permissions:
|
|
contents: write
|
|
|
|
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 system dependencies for AppImage
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y libfuse2
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
for i in 1 2 3;
|
|
do
|
|
if npm ci; then
|
|
break
|
|
else
|
|
if [ $i -eq 3 ]; then
|
|
exit 1
|
|
fi
|
|
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 x64
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
DEBUG: electron-builder
|
|
run: npm run build && npx electron-builder --linux --x64
|
|
|
|
- name: Build Linux arm64 and armv7l
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: npx electron-builder --linux --arm64 --armv7l
|
|
|
|
- name: Rename Linux artifacts for consistency
|
|
run: |
|
|
cd release
|
|
|
|
if [ -f "termix_linux_amd64_deb.deb" ]; then
|
|
mv "termix_linux_amd64_deb.deb" "termix_linux_x64_deb.deb"
|
|
fi
|
|
|
|
if [ -f "termix_linux_x86_64_appimage.AppImage" ]; then
|
|
mv "termix_linux_x86_64_appimage.AppImage" "termix_linux_x64_appimage.AppImage"
|
|
fi
|
|
|
|
cd ..
|
|
|
|
- name: Upload Linux x64 AppImage
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_x64_appimage.AppImage') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_x64_appimage
|
|
path: release/termix_linux_x64_appimage.AppImage
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux arm64 AppImage
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_arm64_appimage.AppImage') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_arm64_appimage
|
|
path: release/termix_linux_arm64_appimage.AppImage
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux armv7l AppImage
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_armv7l_appimage.AppImage') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_armv7l_appimage
|
|
path: release/termix_linux_armv7l_appimage.AppImage
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux x64 DEB
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_x64_deb.deb') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_x64_deb
|
|
path: release/termix_linux_x64_deb.deb
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux arm64 DEB
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_arm64_deb.deb') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_arm64_deb
|
|
path: release/termix_linux_arm64_deb.deb
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux armv7l DEB
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_armv7l_deb.deb') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_armv7l_deb
|
|
path: release/termix_linux_armv7l_deb.deb
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux x64 tar.gz
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_x64_portable.tar.gz') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_x64_portable
|
|
path: release/termix_linux_x64_portable.tar.gz
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux arm64 tar.gz
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_arm64_portable.tar.gz') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_arm64_portable
|
|
path: release/termix_linux_arm64_portable.tar.gz
|
|
retention-days: 30
|
|
|
|
- name: Upload Linux armv7l tar.gz
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_armv7l_portable.tar.gz') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_armv7l_portable
|
|
path: release/termix_linux_armv7l_portable.tar.gz
|
|
retention-days: 30
|
|
|
|
- name: Install Flatpak builder and dependencies
|
|
run: |
|
|
sudo apt-get update
|
|
sudo apt-get install -y flatpak flatpak-builder imagemagick
|
|
|
|
- name: Add Flathub repository
|
|
run: |
|
|
sudo flatpak remote-add --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
|
|
|
|
- name: Install Flatpak runtime and SDK
|
|
run: |
|
|
sudo flatpak install -y flathub org.freedesktop.Platform//24.08
|
|
sudo flatpak install -y flathub org.freedesktop.Sdk//24.08
|
|
sudo flatpak install -y flathub org.electronjs.Electron2.BaseApp//24.08
|
|
|
|
- name: Get version for Flatpak
|
|
id: flatpak-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
|
|
|
|
- name: Prepare Flatpak files
|
|
run: |
|
|
VERSION="${{ steps.flatpak-version.outputs.version }}"
|
|
RELEASE_DATE="${{ steps.flatpak-version.outputs.release_date }}"
|
|
|
|
CHECKSUM_X64=$(sha256sum "release/termix_linux_x64_appimage.AppImage" | awk '{print $1}')
|
|
CHECKSUM_ARM64=$(sha256sum "release/termix_linux_arm64_appimage.AppImage" | awk '{print $1}')
|
|
|
|
mkdir -p flatpak-build
|
|
cp flatpak/com.karmaa.termix.yml flatpak-build/
|
|
cp flatpak/com.karmaa.termix.desktop flatpak-build/
|
|
cp flatpak/com.karmaa.termix.metainfo.xml flatpak-build/
|
|
cp public/icon.svg flatpak-build/com.karmaa.termix.svg
|
|
convert public/icon.png -resize 256x256 flatpak-build/icon-256.png
|
|
convert public/icon.png -resize 128x128 flatpak-build/icon-128.png
|
|
|
|
cd flatpak-build
|
|
sed -i "s|https://github.com/Termix-SSH/Termix/releases/download/release-VERSION_PLACEHOLDER-tag/termix_linux_x64_appimage.AppImage|file://$(realpath ../release/termix_linux_x64_appimage.AppImage)|g" com.karmaa.termix.yml
|
|
sed -i "s|https://github.com/Termix-SSH/Termix/releases/download/release-VERSION_PLACEHOLDER-tag/termix_linux_arm64_appimage.AppImage|file://$(realpath ../release/termix_linux_arm64_appimage.AppImage)|g" com.karmaa.termix.yml
|
|
sed -i "s/CHECKSUM_X64_PLACEHOLDER/$CHECKSUM_X64/g" com.karmaa.termix.yml
|
|
sed -i "s/CHECKSUM_ARM64_PLACEHOLDER/$CHECKSUM_ARM64/g" com.karmaa.termix.yml
|
|
sed -i "s/VERSION_PLACEHOLDER/$VERSION/g" com.karmaa.termix.metainfo.xml
|
|
sed -i "s/DATE_PLACEHOLDER/$RELEASE_DATE/g" com.karmaa.termix.metainfo.xml
|
|
|
|
- name: Build Flatpak bundle
|
|
run: |
|
|
cd flatpak-build
|
|
flatpak-builder --repo=repo --force-clean --disable-rofiles-fuse build-dir com.karmaa.termix.yml
|
|
|
|
# Determine the architecture
|
|
ARCH=$(uname -m)
|
|
if [ "$ARCH" = "x86_64" ]; then
|
|
FLATPAK_ARCH="x86_64"
|
|
elif [ "$ARCH" = "aarch64" ]; then
|
|
FLATPAK_ARCH="aarch64"
|
|
else
|
|
FLATPAK_ARCH="$ARCH"
|
|
fi
|
|
|
|
# Build bundle for the current architecture
|
|
flatpak build-bundle repo ../release/termix_linux_flatpak.flatpak com.karmaa.termix --runtime-repo=https://flathub.org/repo/flathub.flatpakrepo
|
|
|
|
- name: Create flatpakref file
|
|
run: |
|
|
VERSION="${{ steps.flatpak-version.outputs.version }}"
|
|
cp flatpak/com.karmaa.termix.flatpakref release/
|
|
sed -i "s|VERSION_PLACEHOLDER|release-${VERSION}-tag|g" release/com.karmaa.termix.flatpakref
|
|
|
|
- name: Upload Flatpak bundle
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_linux_flatpak.flatpak') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_flatpak
|
|
path: release/termix_linux_flatpak.flatpak
|
|
retention-days: 30
|
|
|
|
- name: Upload Flatpakref
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/com.karmaa.termix.flatpakref') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_linux_flatpakref
|
|
path: release/com.karmaa.termix.flatpakref
|
|
retention-days: 30
|
|
|
|
build-macos:
|
|
runs-on: macos-latest
|
|
if: github.event.inputs.build_type == 'macos' || github.event.inputs.build_type == 'all'
|
|
needs: []
|
|
permissions:
|
|
contents: write
|
|
|
|
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: |
|
|
for i in 1 2 3;
|
|
do
|
|
if npm ci; then
|
|
break
|
|
else
|
|
if [ $i -eq 3 ]; then
|
|
exit 1
|
|
fi
|
|
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
|
|
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
|
|
|
|
echo -n "$MAC_BUILD_CERTIFICATE_BASE64" | base64 --decode -o $APP_CERT_PATH
|
|
|
|
if [ -n "$MAC_INSTALLER_CERTIFICATE_BASE64" ]; then
|
|
echo -n "$MAC_INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $INSTALLER_CERT_PATH
|
|
fi
|
|
|
|
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
|
|
|
|
security import $APP_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
|
|
if [ -f "$INSTALLER_CERT_PATH" ]; then
|
|
security import $INSTALLER_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
fi
|
|
|
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
|
|
|
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
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
BUILD_VERSION="${{ github.run_number }}"
|
|
|
|
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
|
|
|
|
- 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
|
|
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
|
|
|
|
echo -n "$DEVELOPER_ID_CERTIFICATE_BASE64" | base64 --decode -o $DEV_CERT_PATH
|
|
|
|
if [ -n "$DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64" ]; then
|
|
echo -n "$DEVELOPER_ID_INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $DEV_INSTALLER_CERT_PATH
|
|
fi
|
|
|
|
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
|
|
|
|
security import $DEV_CERT_PATH -P "$DEVELOPER_ID_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
|
|
if [ -f "$DEV_INSTALLER_CERT_PATH" ]; then
|
|
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
|
|
|
|
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: |
|
|
if [ "${{ steps.check_certs.outputs.has_certs }}" != "true" ]; then
|
|
npm run build
|
|
fi
|
|
export GH_TOKEN="${{ secrets.GITHUB_TOKEN }}"
|
|
npx electron-builder --mac dmg --universal --x64 --arm64 --publish never
|
|
|
|
- name: Upload macOS MAS PKG
|
|
if: steps.check_certs.outputs.has_certs == 'true' && hashFiles('release/termix_macos_universal_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_universal_mas
|
|
path: release/termix_macos_universal_mas.pkg
|
|
retention-days: 30
|
|
if-no-files-found: warn
|
|
|
|
- name: Upload macOS Universal DMG
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_macos_universal_dmg.dmg') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_macos_universal_dmg
|
|
path: release/termix_macos_universal_dmg.dmg
|
|
retention-days: 30
|
|
|
|
- name: Upload macOS x64 DMG
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_macos_x64_dmg.dmg') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_macos_x64_dmg
|
|
path: release/termix_macos_x64_dmg.dmg
|
|
retention-days: 30
|
|
|
|
- name: Upload macOS arm64 DMG
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('release/termix_macos_arm64_dmg.dmg') != '' && github.event.inputs.artifact_destination != 'none'
|
|
with:
|
|
name: termix_macos_arm64_dmg
|
|
path: release/termix_macos_arm64_dmg.dmg
|
|
retention-days: 30
|
|
|
|
- name: Get version for Homebrew
|
|
id: homebrew-version
|
|
run: |
|
|
VERSION=$(node -p "require('./package.json').version")
|
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
|
|
- name: Generate Homebrew Cask
|
|
if: hashFiles('release/termix_macos_universal_dmg.dmg') != '' && (github.event.inputs.artifact_destination == 'file' || github.event.inputs.artifact_destination == 'release')
|
|
run: |
|
|
VERSION="${{ steps.homebrew-version.outputs.version }}"
|
|
DMG_PATH="release/termix_macos_universal_dmg.dmg"
|
|
|
|
CHECKSUM=$(shasum -a 256 "$DMG_PATH" | awk '{print $1}')
|
|
|
|
mkdir -p homebrew-generated
|
|
cp Casks/termix.rb homebrew-generated/termix.rb
|
|
|
|
sed -i '' "s/VERSION_PLACEHOLDER/$VERSION/g" homebrew-generated/termix.rb
|
|
sed -i '' "s/CHECKSUM_PLACEHOLDER/$CHECKSUM/g" homebrew-generated/termix.rb
|
|
sed -i '' "s|version \".*\"|version \"$VERSION\"|g" homebrew-generated/termix.rb
|
|
sed -i '' "s|sha256 \".*\"|sha256 \"$CHECKSUM\"|g" homebrew-generated/termix.rb
|
|
sed -i '' "s|release-[0-9.]*-tag|release-$VERSION-tag|g" homebrew-generated/termix.rb
|
|
|
|
- name: Upload Homebrew Cask as artifact
|
|
uses: actions/upload-artifact@v4
|
|
if: hashFiles('homebrew-generated/termix.rb') != '' && github.event.inputs.artifact_destination == 'file'
|
|
with:
|
|
name: termix_macos_homebrew_cask
|
|
path: homebrew-generated/termix.rb
|
|
retention-days: 30
|
|
|
|
- name: Upload Homebrew Cask to release
|
|
if: hashFiles('homebrew-generated/termix.rb') != '' && github.event.inputs.artifact_destination == 'release'
|
|
env:
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
VERSION="${{ steps.homebrew-version.outputs.version }}"
|
|
RELEASE_TAG="release-$VERSION-tag"
|
|
|
|
gh release list --repo ${{ github.repository }} --limit 100 | grep -q "$RELEASE_TAG" || {
|
|
echo "Release $RELEASE_TAG not found"
|
|
exit 1
|
|
}
|
|
|
|
gh release upload "$RELEASE_TAG" homebrew-generated/termix.rb --repo ${{ github.repository }} --clobber
|
|
|
|
- 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'
|
|
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
|
|
|
|
- name: Download and prepare MSI info from public release
|
|
id: msi-info
|
|
run: |
|
|
$VERSION = "${{ steps.package-version.outputs.version }}"
|
|
$MSI_NAME = "termix_windows_x64_msi.msi"
|
|
$DOWNLOAD_URL = "https://github.com/Termix-SSH/Termix/releases/download/release-$($VERSION)-tag/$($MSI_NAME)"
|
|
|
|
Write-Host "Downloading from $DOWNLOAD_URL"
|
|
New-Item -ItemType Directory -Force -Path "release_asset"
|
|
$DOWNLOAD_PATH = "release_asset\$MSI_NAME"
|
|
|
|
try {
|
|
Invoke-WebRequest -Uri $DOWNLOAD_URL -OutFile $DOWNLOAD_PATH -UseBasicParsing
|
|
} catch {
|
|
Write-Error "Failed to download MSI from $DOWNLOAD_URL. Please ensure the release and asset exist."
|
|
exit 1
|
|
}
|
|
|
|
$CHECKSUM = (Get-FileHash -Path $DOWNLOAD_PATH -Algorithm SHA256).Hash
|
|
echo "msi_name=$MSI_NAME" >> $env:GITHUB_OUTPUT
|
|
echo "checksum=$CHECKSUM" >> $env:GITHUB_OUTPUT
|
|
|
|
- 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 }}"
|
|
|
|
$DOWNLOAD_URL = "https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$MSI_NAME"
|
|
|
|
New-Item -ItemType Directory -Force -Path "choco-build"
|
|
Copy-Item -Path "chocolatey\*" -Destination "choco-build" -Recurse -Force
|
|
|
|
$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))
|
|
|
|
$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))
|
|
|
|
- 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
|
|
choco pack termix-ssh.nuspec
|
|
|
|
if ($LASTEXITCODE -ne 0) {
|
|
throw "Chocolatey push failed with exit code $LASTEXITCODE"
|
|
}
|
|
|
|
- name: Check for Chocolatey API Key
|
|
id: check_choco_key
|
|
run: |
|
|
if ("${{ secrets.CHOCOLATEY_API_KEY }}" -ne "") {
|
|
echo "has_key=true" >> $env:GITHUB_OUTPUT
|
|
}
|
|
|
|
- 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) {
|
|
} else {
|
|
throw "Chocolatey push failed with exit code $LASTEXITCODE"
|
|
}
|
|
} catch {
|
|
}
|
|
|
|
- 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: []
|
|
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
|
|
|
|
- name: Download and prepare AppImage info from public release
|
|
id: appimage-info
|
|
run: |
|
|
VERSION="${{ steps.package-version.outputs.version }}"
|
|
mkdir -p release_assets
|
|
|
|
APPIMAGE_X64_NAME="termix_linux_x64_appimage.AppImage"
|
|
URL_X64="https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$APPIMAGE_X64_NAME"
|
|
PATH_X64="release_assets/$APPIMAGE_X64_NAME"
|
|
echo "Downloading x64 AppImage from $URL_X64"
|
|
curl -L -o "$PATH_X64" "$URL_X64"
|
|
chmod +x "$PATH_X64"
|
|
CHECKSUM_X64=$(sha256sum "$PATH_X64" | awk '{print $1}')
|
|
|
|
APPIMAGE_ARM64_NAME="termix_linux_arm64_appimage.AppImage"
|
|
URL_ARM64="https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$APPIMAGE_ARM64_NAME"
|
|
PATH_ARM64="release_assets/$APPIMAGE_ARM64_NAME"
|
|
echo "Downloading arm64 AppImage from $URL_ARM64"
|
|
curl -L -o "$PATH_ARM64" "$URL_ARM64"
|
|
chmod +x "$PATH_ARM64"
|
|
CHECKSUM_ARM64=$(sha256sum "$PATH_ARM64" | 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
|
|
|
|
- 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 }}"
|
|
|
|
mkdir -p flatpak-submission
|
|
|
|
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/
|
|
|
|
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
|
|
|
|
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
|
|
|
|
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
|
|
|
|
- name: Upload Flatpak submission as artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: flatpak-submission
|
|
path: flatpak-submission/*
|
|
retention-days: 30
|
|
|
|
submit-to-homebrew:
|
|
runs-on: macos-latest
|
|
if: github.event.inputs.artifact_destination == 'submit'
|
|
needs: []
|
|
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
|
|
|
|
- name: Download and prepare DMG info from public release
|
|
id: dmg-info
|
|
run: |
|
|
VERSION="${{ steps.package-version.outputs.version }}"
|
|
DMG_NAME="termix_macos_universal_dmg.dmg"
|
|
URL="https://github.com/Termix-SSH/Termix/releases/download/release-$VERSION-tag/$DMG_NAME"
|
|
|
|
mkdir -p release_asset
|
|
PATH="release_asset/$DMG_NAME"
|
|
echo "Downloading DMG from $URL"
|
|
curl -L -o "$PATH" "$URL"
|
|
|
|
CHECKSUM=$(shasum -a 256 "$PATH" | awk '{print $1}')
|
|
|
|
echo "dmg_name=$DMG_NAME" >> $GITHUB_OUTPUT
|
|
echo "checksum=$CHECKSUM" >> $GITHUB_OUTPUT
|
|
|
|
- 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 }}"
|
|
|
|
mkdir -p homebrew-submission/Casks/t
|
|
|
|
cp Casks/termix.rb homebrew-submission/Casks/t/termix.rb
|
|
|
|
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
|
|
|
|
- name: Verify Cask syntax
|
|
run: |
|
|
ruby -c homebrew-submission/Casks/t/termix.rb
|
|
|
|
- name: Upload Homebrew submission as artifact
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: homebrew-submission
|
|
path: homebrew-submission/*
|
|
retention-days: 30
|
|
|
|
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 tag
|
|
id: get_release
|
|
run: |
|
|
echo "RELEASE_TAG=$(gh release list --repo ${{ github.repository }} --limit 1 --json tagName -q '.[0].tagName')" >> $GITHUB_ENV
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
|
|
- name: Upload artifacts to latest release
|
|
run: |
|
|
cd artifacts
|
|
for dir in */; do
|
|
cd "$dir"
|
|
for file in *;
|
|
do
|
|
if [ -f "$file" ]; then
|
|
gh release upload "$RELEASE_TAG" "$file" --repo ${{ github.repository }} --clobber
|
|
fi
|
|
done
|
|
cd ..
|
|
done
|
|
env:
|
|
GH_TOKEN: ${{ github.token }}
|
|
|
|
submit-to-testflight:
|
|
runs-on: macos-latest
|
|
if: github.event.inputs.artifact_destination == 'submit'
|
|
needs: []
|
|
permissions:
|
|
contents: write
|
|
|
|
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: |
|
|
for i in 1 2 3;
|
|
do
|
|
if npm ci; then
|
|
break
|
|
else
|
|
if [ $i -eq 3 ]; then
|
|
exit 1
|
|
fi
|
|
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
|
|
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
|
|
|
|
echo -n "$MAC_BUILD_CERTIFICATE_BASE64" | base64 --decode -o $APP_CERT_PATH
|
|
|
|
if [ -n "$MAC_INSTALLER_CERTIFICATE_BASE64" ]; then
|
|
echo -n "$MAC_INSTALLER_CERTIFICATE_BASE64" | base64 --decode -o $INSTALLER_CERT_PATH
|
|
fi
|
|
|
|
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
|
|
|
|
security import $APP_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
|
|
if [ -f "$INSTALLER_CERT_PATH" ]; then
|
|
security import $INSTALLER_CERT_PATH -P "$MAC_P12_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
|
|
fi
|
|
|
|
security list-keychain -d user -s $KEYCHAIN_PATH
|
|
|
|
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
|
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
run: |
|
|
CURRENT_VERSION=$(node -p "require('./package.json').version")
|
|
BUILD_VERSION="${{ github.run_number }}"
|
|
|
|
npm run build && npx electron-builder --mac mas --universal --config.buildVersion="$BUILD_VERSION"
|
|
|
|
- name: Check for App Store Connect API credentials
|
|
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
|
|
fi
|
|
|
|
- name: Setup Ruby for Fastlane
|
|
if: steps.check_asc_creds.outputs.has_credentials == 'true'
|
|
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'
|
|
run: |
|
|
gem install fastlane -N
|
|
|
|
- name: Deploy to App Store Connect (TestFlight)
|
|
if: steps.check_asc_creds.outputs.has_credentials == 'true'
|
|
run: |
|
|
PKG_FILE=$(find artifact-mas -name "*.pkg" -type f | head -n 1)
|
|
if [ -z "$PKG_FILE" ]; then
|
|
echo "PKG file not found, exiting."
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p ~/private_keys
|
|
echo "${{ secrets.APPLE_KEY_CONTENT }}" | base64 --decode > ~/private_keys/AuthKey_${{ secrets.APPLE_KEY_ID }}.p8
|
|
|
|
xcrun altool --upload-app -f "$PKG_FILE" \
|
|
--type macos \
|
|
--apiKey "${{ secrets.APPLE_KEY_ID }}" \
|
|
--apiIssuer "${{ secrets.APPLE_ISSUER_ID }}"
|
|
continue-on-error: true
|
|
|
|
- name: Clean up keychains
|
|
if: always()
|
|
run: |
|
|
security delete-keychain $RUNNER_TEMP/app-signing.keychain-db || true
|