Skip to content

Commit a7cd6cb

Browse files
committed
ci: add GitHub Actions CI/CD workflows
1 parent e2f8aa3 commit a7cd6cb

2 files changed

Lines changed: 257 additions & 0 deletions

File tree

.github/workflows/build.yml

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
name: Build & Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: "Release version (e.g., 0.2.0)"
8+
required: true
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
14+
jobs:
15+
build:
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
include:
20+
- platform: macos
21+
os: macos-latest
22+
rust-targets: aarch64-apple-darwin,x86_64-apple-darwin
23+
tauri-args: "--target universal-apple-darwin"
24+
- platform: windows
25+
os: windows-latest
26+
rust-targets: x86_64-pc-windows-msvc
27+
tauri-args: ""
28+
- platform: linux
29+
os: ubuntu-22.04
30+
rust-targets: x86_64-unknown-linux-gnu
31+
tauri-args: ""
32+
33+
runs-on: ${{ matrix.os }}
34+
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@v4
38+
39+
# ── Linux system dependencies ──
40+
- name: Install Linux system dependencies
41+
if: matrix.platform == 'linux'
42+
run: |
43+
sudo apt-get update
44+
sudo apt-get install -y \
45+
libwebkit2gtk-4.1-dev \
46+
libappindicator3-dev \
47+
librsvg2-dev \
48+
patchelf \
49+
libssl-dev \
50+
libgtk-3-dev
51+
52+
# ── Rust ──
53+
- name: Setup Rust toolchain
54+
uses: dtolnay/rust-toolchain@stable
55+
with:
56+
targets: ${{ matrix.rust-targets }}
57+
58+
- name: Rust cache
59+
uses: Swatinem/rust-cache@v2
60+
with:
61+
workspaces: src-tauri
62+
63+
# ── Bun ──
64+
- name: Setup Bun
65+
uses: oven-sh/setup-bun@v2
66+
67+
- name: Install frontend dependencies
68+
run: bun install --frozen-lockfile
69+
70+
# ── Python sidecar ──
71+
- name: Setup Python
72+
uses: actions/setup-python@v5
73+
with:
74+
python-version: "3.12"
75+
76+
- name: Cache Python sidecar venv
77+
uses: actions/cache@v4
78+
with:
79+
path: sidecar/.venv
80+
key: ${{ runner.os }}-sidecar-venv-${{ hashFiles('sidecar/requirements.txt') }}
81+
82+
- name: Create sidecar venv and install deps (Unix)
83+
if: matrix.platform != 'windows'
84+
run: |
85+
python3 -m venv sidecar/.venv
86+
sidecar/.venv/bin/pip install --upgrade pip
87+
sidecar/.venv/bin/pip install -r sidecar/requirements.txt
88+
89+
- name: Create sidecar venv and install deps (Windows)
90+
if: matrix.platform == 'windows'
91+
shell: pwsh
92+
run: |
93+
python -m venv sidecar/.venv
94+
sidecar/.venv/Scripts/pip install --upgrade pip
95+
sidecar/.venv/Scripts/pip install -r sidecar/requirements.txt
96+
97+
# ── Version injection ──
98+
- name: Set version (Unix)
99+
if: matrix.platform != 'windows'
100+
run: |
101+
# package.json
102+
jq '.version = "${{ inputs.version }}"' package.json > tmp.json && mv tmp.json package.json
103+
# tauri.conf.json
104+
jq '.version = "${{ inputs.version }}"' src-tauri/tauri.conf.json > tmp.json && mv tmp.json src-tauri/tauri.conf.json
105+
# Cargo.toml — only replace the first version line (package version)
106+
sed -i'' -e '0,/^version = ".*"/s//version = "${{ inputs.version }}"/' src-tauri/Cargo.toml
107+
108+
- name: Set version (Windows)
109+
if: matrix.platform == 'windows'
110+
shell: pwsh
111+
run: |
112+
# package.json
113+
$pkg = Get-Content package.json -Raw | ConvertFrom-Json
114+
$pkg.version = "${{ inputs.version }}"
115+
$pkg | ConvertTo-Json -Depth 10 | Set-Content package.json
116+
117+
# tauri.conf.json
118+
$tauri = Get-Content src-tauri/tauri.conf.json -Raw | ConvertFrom-Json
119+
$tauri.version = "${{ inputs.version }}"
120+
$tauri | ConvertTo-Json -Depth 10 | Set-Content src-tauri/tauri.conf.json
121+
122+
# Cargo.toml
123+
$cargo = Get-Content src-tauri/Cargo.toml -Raw
124+
$cargo = $cargo -replace '(?m)^version = ".*?"', "version = `"${{ inputs.version }}`""
125+
# Only replace the first occurrence (package version)
126+
Set-Content src-tauri/Cargo.toml $cargo
127+
128+
# ── Build ──
129+
- name: Build Tauri app
130+
run: bun run tauri build ${{ matrix.tauri-args }}
131+
132+
# ── macOS: inject sidecar & re-create DMG ──
133+
- name: Inject sidecar into macOS bundle
134+
if: matrix.platform == 'macos'
135+
run: |
136+
APP_DIR="src-tauri/target/universal-apple-darwin/release/bundle/macos/SwiftSSH.app"
137+
cp -r sidecar "$APP_DIR/Contents/MacOS/sidecar"
138+
find "$APP_DIR/Contents/MacOS/sidecar" -name "__pycache__" -type d -exec rm -rf {} +
139+
find "$APP_DIR/Contents/MacOS/sidecar" -name ".venv" -path "*/sidecar/.venv" -prune -exec find {} -name "__pycache__" -type d -exec rm -rf {} + \;
140+
141+
# Re-create DMG with sidecar included
142+
DMG_NAME="SwiftSSH_${{ inputs.version }}_macos_universal.dmg"
143+
hdiutil create -volname "SwiftSSH" -srcfolder "$APP_DIR" -ov -format UDZO "$DMG_NAME"
144+
145+
- name: Upload macOS artifacts
146+
if: matrix.platform == 'macos'
147+
uses: actions/upload-artifact@v4
148+
with:
149+
name: SwiftSSH-macos-universal
150+
path: SwiftSSH_*.dmg
151+
152+
# ── Windows: create portable zip ──
153+
- name: Package Windows distribution
154+
if: matrix.platform == 'windows'
155+
shell: pwsh
156+
run: |
157+
$outDir = "SwiftSSH-windows"
158+
New-Item -ItemType Directory -Path $outDir -Force
159+
Copy-Item "src-tauri/target/release/SwiftSSH.exe" "$outDir/"
160+
Copy-Item -Recurse "sidecar" "$outDir/sidecar"
161+
Get-ChildItem -Path "$outDir/sidecar" -Recurse -Directory -Filter "__pycache__" | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue
162+
Compress-Archive -Path "$outDir/*" -DestinationPath "SwiftSSH_${{ inputs.version }}_windows_x64.zip"
163+
164+
- name: Upload Windows artifacts
165+
if: matrix.platform == 'windows'
166+
uses: actions/upload-artifact@v4
167+
with:
168+
name: SwiftSSH-windows-x64
169+
path: |
170+
SwiftSSH_*.zip
171+
src-tauri/target/release/bundle/msi/*.msi
172+
src-tauri/target/release/bundle/nsis/*.exe
173+
174+
# ── Linux: create portable tarball ──
175+
- name: Package Linux distribution
176+
if: matrix.platform == 'linux'
177+
run: |
178+
mkdir -p SwiftSSH-linux
179+
# Tauri uses lowercase product name on Linux
180+
cp "src-tauri/target/release/swift-ssh" "SwiftSSH-linux/" 2>/dev/null \
181+
|| cp "src-tauri/target/release/swiftssh" "SwiftSSH-linux/" 2>/dev/null \
182+
|| cp src-tauri/target/release/swift* "SwiftSSH-linux/"
183+
cp -r sidecar SwiftSSH-linux/sidecar
184+
find SwiftSSH-linux/sidecar -name "__pycache__" -type d -exec rm -rf {} +
185+
tar czf "SwiftSSH_${{ inputs.version }}_linux_x64.tar.gz" SwiftSSH-linux/
186+
187+
- name: Upload Linux artifacts
188+
if: matrix.platform == 'linux'
189+
uses: actions/upload-artifact@v4
190+
with:
191+
name: SwiftSSH-linux-x64
192+
path: |
193+
SwiftSSH_*.tar.gz
194+
src-tauri/target/release/bundle/deb/*.deb
195+
src-tauri/target/release/bundle/appimage/*.AppImage

.github/workflows/ci.yml

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
frontend-checks:
15+
name: Frontend
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- uses: oven-sh/setup-bun@v2
21+
22+
- run: bun install --frozen-lockfile
23+
24+
- name: Typecheck & build
25+
run: bun run build
26+
27+
rust-checks:
28+
name: Rust
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
33+
- name: Install system dependencies
34+
run: |
35+
sudo apt-get update
36+
sudo apt-get install -y \
37+
libwebkit2gtk-4.1-dev \
38+
libappindicator3-dev \
39+
librsvg2-dev \
40+
patchelf \
41+
libssl-dev \
42+
libgtk-3-dev
43+
44+
- uses: dtolnay/rust-toolchain@stable
45+
with:
46+
components: clippy, rustfmt
47+
48+
- uses: Swatinem/rust-cache@v2
49+
with:
50+
workspaces: src-tauri
51+
52+
- uses: oven-sh/setup-bun@v2
53+
54+
- run: bun install --frozen-lockfile
55+
56+
- name: Clippy
57+
working-directory: src-tauri
58+
run: cargo clippy --all-targets -- -D warnings
59+
60+
- name: Rustfmt
61+
working-directory: src-tauri
62+
run: cargo fmt --check

0 commit comments

Comments
 (0)