Skip to content

Commit eaae143

Browse files
committed
feat: add CLI support with GUI and server mode, enhance release workflow for Linux binaries
1 parent 2d93b4d commit eaae143

File tree

6 files changed

+76
-23
lines changed

6 files changed

+76
-23
lines changed

.github/workflows/release.yml

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,6 @@ jobs:
5353
args: ''
5454
rust_targets: ''
5555
name: linux-x86_64
56-
# Linux ARM64
57-
- platform: ubuntu-22.04-arm
58-
args: ''
59-
rust_targets: ''
60-
name: linux-aarch64
6156
# Windows
6257
- platform: windows-latest
6358
args: ''
@@ -118,17 +113,46 @@ jobs:
118113
releaseId: ${{ needs.create-release.outputs.release_id }}
119114
args: ${{ matrix.args }}
120115

121-
- name: Package standalone binary (Linux)
122-
if: contains(matrix.name, 'linux')
116+
build-cli:
117+
needs: create-release
118+
permissions:
119+
contents: write
120+
strategy:
121+
fail-fast: false
122+
matrix:
123+
include:
124+
- platform: ubuntu-22.04
125+
target: x86_64-unknown-linux-gnu
126+
arch: amd64
127+
- platform: ubuntu-22.04-arm
128+
target: aarch64-unknown-linux-gnu
129+
arch: aarch64
130+
131+
runs-on: ${{ matrix.platform }}
132+
133+
steps:
134+
- name: Checkout
135+
uses: actions/checkout@v4
136+
137+
- name: Install Rust stable
138+
uses: dtolnay/rust-toolchain@stable
139+
140+
- name: Rust cache
141+
uses: swatinem/rust-cache@v2
142+
with:
143+
workspaces: './src-tauri -> target'
144+
145+
- name: Build CLI binary (no GUI dependencies)
146+
working-directory: src-tauri
147+
run: cargo build --release --no-default-features
148+
149+
- name: Package standalone binary
123150
run: |
124-
ARCH=$([[ "${{ matrix.name }}" == *"aarch64"* ]] && echo "aarch64" || echo "amd64")
125-
BINARY="src-tauri/target/release/fetch-github-hosts"
126-
TAR_NAME="fetch-github-hosts_linux_${ARCH}.tar.gz"
127-
tar -czf "$TAR_NAME" -C "$(dirname "$BINARY")" "$(basename "$BINARY")"
151+
TAR_NAME="fetch-github-hosts_linux_${{ matrix.arch }}.tar.gz"
152+
tar -czf "$TAR_NAME" -C "src-tauri/target/release" "fetch-github-hosts"
128153
echo "TAR_NAME=$TAR_NAME" >> "$GITHUB_ENV"
129154
130-
- name: Upload standalone binary (Linux)
131-
if: contains(matrix.name, 'linux')
155+
- name: Upload standalone binary
132156
env:
133157
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
134158
run: |

src-tauri/Cargo.toml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ rust-version = "1.77.2"
1212
name = "app_lib"
1313
crate-type = ["staticlib", "cdylib", "rlib"]
1414

15+
[features]
16+
default = ["gui"]
17+
gui = ["dep:tauri", "dep:tauri-plugin-log", "dep:tauri-plugin-shell"]
18+
1519
[build-dependencies]
1620
tauri-build = { version = "2.5.4", features = [] }
1721

@@ -20,9 +24,9 @@ serde_json = "1.0"
2024
serde = { version = "1.0", features = ["derive"] }
2125
serde_yaml = "0.9"
2226
log = "0.4"
23-
tauri = { version = "2.10.0", features = ["macos-private-api", "tray-icon"] }
24-
tauri-plugin-log = "2"
25-
tauri-plugin-shell = "2"
27+
tauri = { version = "2.10.0", features = ["macos-private-api", "tray-icon"], optional = true }
28+
tauri-plugin-log = { version = "2", optional = true }
29+
tauri-plugin-shell = { version = "2", optional = true }
2630
tokio = { version = "1", features = ["full"] }
2731
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
2832
dns-lookup = "2"

src-tauri/build.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
fn main() {
2-
tauri_build::build()
2+
#[cfg(feature = "gui")]
3+
tauri_build::build();
34
}

src-tauri/src/lib.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
pub mod cli;
2+
#[cfg(feature = "gui")]
23
mod commands;
3-
mod config;
4-
mod dns;
5-
mod hosts;
6-
mod models;
7-
mod services;
4+
pub(crate) mod config;
5+
pub(crate) mod dns;
6+
pub(crate) mod hosts;
7+
pub(crate) mod models;
8+
pub(crate) mod services;
89

10+
#[cfg(feature = "gui")]
911
use std::sync::Mutex;
12+
#[cfg(feature = "gui")]
1013
use services::{ClientState, ServerState};
14+
#[cfg(feature = "gui")]
1115
use tauri::{
1216
Manager,
1317
menu::{MenuBuilder, MenuItemBuilder},
1418
tray::TrayIconBuilder,
1519
};
1620

1721
/// Detect system language and return supported locale code
18-
fn detect_system_lang() -> &'static str {
22+
pub fn detect_system_lang() -> &'static str {
1923
let lang = sys_locale::get_locale().unwrap_or_else(|| "en-US".to_string());
2024
if lang.starts_with("zh") {
2125
"zh-CN"
@@ -27,6 +31,7 @@ fn detect_system_lang() -> &'static str {
2731
}
2832

2933
/// Known hosts origins (must match frontend)
34+
#[cfg(feature = "gui")]
3035
fn get_hosts_url(select_origin: &str, custom_url: &str, method: &str) -> String {
3136
if method == "custom" && !custom_url.is_empty() {
3237
return custom_url.to_string();
@@ -38,6 +43,7 @@ fn get_hosts_url(select_origin: &str, custom_url: &str, method: &str) -> String
3843
}
3944

4045
/// Get tray menu text by key and locale
46+
#[cfg(feature = "gui")]
4147
fn tray_text(key: &str, lang: &str) -> &'static str {
4248
match (key, lang) {
4349
("show", "zh-CN") => "显示主窗口",
@@ -76,6 +82,7 @@ fn tray_text(key: &str, lang: &str) -> &'static str {
7682
}
7783
}
7884

85+
#[cfg(feature = "gui")]
7986
#[cfg_attr(mobile, tauri::mobile_entry_point)]
8087
pub fn run() {
8188
tauri::Builder::default()

src-tauri/src/main.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ fn main() {
1414
});
1515
} else {
1616
// GUI mode: launch Tauri window
17+
#[cfg(feature = "gui")]
1718
app_lib::run();
19+
20+
#[cfg(not(feature = "gui"))]
21+
{
22+
eprintln!("GUI mode is not available in this build.");
23+
eprintln!("Use -m client or -m server for CLI mode.");
24+
eprintln!("Example: fetch-github-hosts -m client");
25+
std::process::exit(1);
26+
}
1827
}
1928
}

src-tauri/src/services.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
1+
#[cfg(feature = "gui")]
12
use tauri::{AppHandle, Emitter};
3+
#[cfg(feature = "gui")]
24
use tokio::sync::oneshot;
35

46
use crate::dns;
57
use crate::hosts;
8+
#[cfg(feature = "gui")]
69
use crate::models::LogPayload;
710

811
/// State for managing client ticker
12+
#[cfg(feature = "gui")]
913
pub struct ClientState {
1014
pub stop_tx: Option<oneshot::Sender<()>>,
1115
}
1216

1317
/// State for managing server ticker
18+
#[cfg(feature = "gui")]
1419
pub struct ServerState {
1520
pub stop_tx: Option<oneshot::Sender<()>>,
1621
}
1722

1823
/// Start the client mode: periodically fetch hosts from remote URL
24+
#[cfg(feature = "gui")]
1925
pub async fn start_client_task(
2026
app: AppHandle,
2127
url: String,
@@ -85,6 +91,7 @@ pub async fn client_fetch_hosts(url: &str) -> Result<(), String> {
8591
}
8692

8793
/// Start the server mode: resolve DNS and serve hosts via HTTP
94+
#[cfg(feature = "gui")]
8895
pub async fn start_server_task(
8996
app: AppHandle,
9097
port: u16,
@@ -160,6 +167,7 @@ pub async fn server_fetch_hosts() -> Result<(), String> {
160167
}
161168

162169
/// Simple HTTP server for serving hosts files (async with graceful shutdown)
170+
#[cfg(feature = "gui")]
163171
async fn start_http_server(port: u16, app: AppHandle, mut shutdown_rx: tokio::sync::watch::Receiver<bool>) {
164172
use tokio::io::{AsyncReadExt, AsyncWriteExt};
165173
use tokio::net::TcpListener;

0 commit comments

Comments
 (0)