Skip to content

Commit b474d66

Browse files
wolfieschclaude
andcommitted
fix: use git dep for fgp-daemon, disable OpenSSL, fix warnings
- Switch from path to git dependency for CI builds - Disable default features on reqwest to avoid OpenSSL - Add #[allow(dead_code)] to unused fields Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7ab7f51 commit b474d66

7 files changed

Lines changed: 136 additions & 47 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ path = "src/main.rs"
1717

1818
[dependencies]
1919
# FGP daemon SDK
20-
fgp-daemon = { path = "../daemon" }
20+
fgp-daemon = { git = "https://github.com/fast-gateway-protocol/daemon.git" }
2121

22-
# HTTP client
23-
reqwest = { version = "0.12", features = ["json", "rustls-tls"] }
22+
# HTTP client (disable default-tls to avoid OpenSSL for cross-compilation)
23+
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
2424

2525
# Serialization
2626
serde = { version = "1", features = ["derive"] }

logs/session_start.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[
2+
{
3+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
4+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
5+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
6+
"hook_event_name": "SessionStart",
7+
"source": "compact"
8+
}
9+
]

logs/user_prompt_submit.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
[
2+
{
3+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
4+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
5+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
6+
"permission_mode": "bypassPermissions",
7+
"hook_event_name": "UserPromptSubmit",
8+
"prompt": "test the github daemon live"
9+
},
10+
{
11+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
12+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
13+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
14+
"permission_mode": "bypassPermissions",
15+
"hook_event_name": "UserPromptSubmit",
16+
"prompt": "Okay, I should be logged into GitHub now. I just went through the authentication procedure via the CLI."
17+
},
18+
{
19+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
20+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
21+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
22+
"permission_mode": "bypassPermissions",
23+
"hook_event_name": "UserPromptSubmit",
24+
"prompt": "commit the github daemon changes"
25+
},
26+
{
27+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
28+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
29+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
30+
"permission_mode": "bypassPermissions",
31+
"hook_event_name": "UserPromptSubmit",
32+
"prompt": "push to github"
33+
},
34+
{
35+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
36+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
37+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
38+
"permission_mode": "bypassPermissions",
39+
"hook_event_name": "UserPromptSubmit",
40+
"prompt": "what's next on the fgp plan"
41+
},
42+
{
43+
"session_id": "57ed67ac-2bd7-4367-9402-225a5ad61c75",
44+
"transcript_path": "/Users/wolfgangschoenberger/.claude/projects/-Users-wolfgangschoenberger-Projects-fgp/57ed67ac-2bd7-4367-9402-225a5ad61c75.jsonl",
45+
"cwd": "/Users/wolfgangschoenberger/Projects/fgp/github",
46+
"permission_mode": "bypassPermissions",
47+
"hook_event_name": "UserPromptSubmit",
48+
"prompt": "yes do the protocol compliance tests"
49+
}
50+
]

src/api/client.rs

Lines changed: 18 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@ use serde::{Deserialize, Serialize};
99
use serde_json::Value;
1010
use std::path::PathBuf;
1111

12-
use crate::models::{
13-
GraphQLResponse, Issue, Notification, PullRequest, Repository, User,
14-
};
12+
use crate::models::{GraphQLResponse, Issue, Notification, PullRequest, Repository, User};
1513

1614
const GRAPHQL_ENDPOINT: &str = "https://api.github.com/graphql";
1715
const REST_ENDPOINT: &str = "https://api.github.com";
@@ -77,12 +75,11 @@ impl GitHubClient {
7775
);
7876
}
7977

80-
let content = std::fs::read_to_string(&config_path)
81-
.context("Failed to read gh config file")?;
78+
let content =
79+
std::fs::read_to_string(&config_path).context("Failed to read gh config file")?;
8280

8381
// Parse YAML config
84-
let config: Value = serde_yaml::from_str(&content)
85-
.context("Failed to parse gh config")?;
82+
let config: Value = serde_yaml::from_str(&content).context("Failed to parse gh config")?;
8683

8784
// Extract token for github.com
8885
let token = config
@@ -107,8 +104,7 @@ impl GitHubClient {
107104
}
108105

109106
// Fall back to ~/.config/gh/hosts.yml
110-
let home = dirs::home_dir()
111-
.context("Could not determine home directory")?;
107+
let home = dirs::home_dir().context("Could not determine home directory")?;
112108

113109
Ok(home.join(".config").join("gh").join("hosts.yml"))
114110
}
@@ -141,14 +137,13 @@ impl GitHubClient {
141137

142138
let text = response.text().await.context("Failed to read response")?;
143139

144-
let result: GraphQLResponse<T> = serde_json::from_str(&text)
145-
.map_err(|e| {
146-
anyhow::anyhow!(
147-
"JSON parse error: {} | Raw: {}",
148-
e,
149-
&text[..text.len().min(500)]
150-
)
151-
})?;
140+
let result: GraphQLResponse<T> = serde_json::from_str(&text).map_err(|e| {
141+
anyhow::anyhow!(
142+
"JSON parse error: {} | Raw: {}",
143+
e,
144+
&text[..text.len().min(500)]
145+
)
146+
})?;
152147

153148
// Check for GraphQL errors
154149
if result.data.is_none() {
@@ -160,9 +155,7 @@ impl GitHubClient {
160155
}
161156
}
162157

163-
result
164-
.data
165-
.context("GraphQL response missing data field")
158+
result.data.context("GraphQL response missing data field")
166159
}
167160

168161
/// Execute a REST API request (GET).
@@ -305,7 +298,9 @@ impl GitHubClient {
305298

306299
let v = match result {
307300
Ok(r) => r.viewer,
308-
Err(e) if e.to_string().contains("user:email") || e.to_string().contains("read:user") => {
301+
Err(e)
302+
if e.to_string().contains("user:email") || e.to_string().contains("read:user") =>
303+
{
309304
// Token lacks email scope, try without
310305
let r: ViewerResponse = self.graphql(query_without_email, None).await?;
311306
r.viewer
@@ -505,6 +500,7 @@ impl GitHubClient {
505500
}
506501

507502
#[derive(Deserialize)]
503+
#[allow(dead_code)]
508504
struct LabelNode {
509505
name: String,
510506
color: String,
@@ -568,12 +564,7 @@ impl GitHubClient {
568564
}
569565

570566
/// Get pull request details with status checks and reviews.
571-
pub async fn get_pr(
572-
&self,
573-
owner: &str,
574-
repo: &str,
575-
pr_number: i32,
576-
) -> Result<PullRequest> {
567+
pub async fn get_pr(&self, owner: &str, repo: &str, pr_number: i32) -> Result<PullRequest> {
577568
let query = r#"
578569
query($owner: String!, $name: String!, $number: Int!) {
579570
repository(owner: $owner, name: $name) {

src/main.rs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use anyhow::{Context, Result};
4646
use clap::{Parser, Subcommand};
4747
use fgp_daemon::{cleanup_socket, FgpServer};
4848
use std::path::Path;
49+
use std::process::Command;
4950

5051
use crate::service::GitHubService;
5152

@@ -133,7 +134,8 @@ fn cmd_start(socket: String, foreground: bool) -> Result<()> {
133134

134135
// Token is resolved inside GitHubService::new
135136
let service = GitHubService::new(None).context("Failed to create GitHubService")?;
136-
let server = FgpServer::new(service, &socket_path).context("Failed to create FGP server")?;
137+
let server =
138+
FgpServer::new(service, &socket_path).context("Failed to create FGP server")?;
137139
server.serve().context("Server error")?;
138140
} else {
139141
// Background mode - daemonize first, THEN create service
@@ -151,10 +153,9 @@ fn cmd_start(socket: String, foreground: bool) -> Result<()> {
151153
.with_env_filter("fgp_github=debug,fgp_daemon=debug")
152154
.init();
153155

154-
let service = GitHubService::new(None)
155-
.context("Failed to create GitHubService")?;
156-
let server = FgpServer::new(service, &socket_path)
157-
.context("Failed to create FGP server")?;
156+
let service = GitHubService::new(None).context("Failed to create GitHubService")?;
157+
let server =
158+
FgpServer::new(service, &socket_path).context("Failed to create FGP server")?;
158159
server.serve().context("Server error")?;
159160
}
160161
Err(e) => {
@@ -171,11 +172,26 @@ fn cmd_stop(socket: String) -> Result<()> {
171172
let socket_path = shellexpand::tilde(&socket).to_string();
172173
let pid_file = format!("{}.pid", socket_path);
173174

175+
if Path::new(&socket_path).exists() {
176+
if let Ok(client) = fgp_daemon::FgpClient::new(&socket_path) {
177+
if let Ok(response) = client.stop() {
178+
if response.ok {
179+
println!("Daemon stopped.");
180+
return Ok(());
181+
}
182+
}
183+
}
184+
}
185+
174186
// Read PID
175187
let pid_str = std::fs::read_to_string(&pid_file)
176188
.context("Failed to read PID file - daemon may not be running")?;
177189
let pid: i32 = pid_str.trim().parse().context("Invalid PID in file")?;
178190

191+
if !pid_matches_process(pid, "fgp-github") {
192+
anyhow::bail!("Refusing to stop PID {}: unexpected process", pid);
193+
}
194+
179195
println!("Stopping fgp-github daemon (PID: {})...", pid);
180196

181197
// Send SIGTERM
@@ -195,6 +211,20 @@ fn cmd_stop(socket: String) -> Result<()> {
195211
Ok(())
196212
}
197213

214+
fn pid_matches_process(pid: i32, expected_name: &str) -> bool {
215+
let output = Command::new("ps")
216+
.args(["-p", &pid.to_string(), "-o", "comm="])
217+
.output();
218+
219+
match output {
220+
Ok(output) if output.status.success() => {
221+
let command = String::from_utf8_lossy(&output.stdout);
222+
command.trim().contains(expected_name)
223+
}
224+
_ => false,
225+
}
226+
}
227+
198228
fn cmd_status(socket: String) -> Result<()> {
199229
let socket_path = shellexpand::tilde(&socket).to_string();
200230

src/models.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ pub struct GraphQLResponse<T> {
109109
pub struct GraphQLError {
110110
pub message: String,
111111
#[serde(default)]
112+
#[allow(dead_code)]
112113
pub path: Option<Vec<serde_json::Value>>,
113114
}
114115

src/service.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,9 @@ impl GitHubService {
7878

7979
fn get_user(&self) -> Result<Value> {
8080
let client = self.client.clone();
81-
let user = self.runtime.block_on(async move { client.get_user().await })?;
81+
let user = self
82+
.runtime
83+
.block_on(async move { client.get_user().await })?;
8284

8385
Ok(serde_json::json!(user))
8486
}
@@ -110,9 +112,9 @@ impl GitHubService {
110112
let state = state.to_string();
111113
let state_for_response = state.clone();
112114

113-
let issues = self.runtime.block_on(async move {
114-
client.list_issues(&owner, &repo, &state, limit).await
115-
})?;
115+
let issues = self
116+
.runtime
117+
.block_on(async move { client.list_issues(&owner, &repo, &state, limit).await })?;
116118

117119
Ok(serde_json::json!({
118120
"repo": repo_str,
@@ -135,9 +137,9 @@ impl GitHubService {
135137
let state = state.to_string();
136138
let state_for_response = state.clone();
137139

138-
let prs = self.runtime.block_on(async move {
139-
client.list_prs(&owner, &repo, &state, limit).await
140-
})?;
140+
let prs = self
141+
.runtime
142+
.block_on(async move { client.list_prs(&owner, &repo, &state, limit).await })?;
141143

142144
Ok(serde_json::json!({
143145
"repo": repo_str,
@@ -160,9 +162,9 @@ impl GitHubService {
160162
let owner = owner.to_string();
161163
let repo = repo.to_string();
162164

163-
let pr = self.runtime.block_on(async move {
164-
client.get_pr(&owner, &repo, number).await
165-
})?;
165+
let pr = self
166+
.runtime
167+
.block_on(async move { client.get_pr(&owner, &repo, number).await })?;
166168

167169
Ok(serde_json::json!(pr))
168170
}
@@ -377,10 +379,16 @@ impl FgpService for GitHubService {
377379

378380
match result {
379381
Ok(true) => {
380-
checks.insert("github_api".into(), HealthStatus::healthy_with_latency(latency));
382+
checks.insert(
383+
"github_api".into(),
384+
HealthStatus::healthy_with_latency(latency),
385+
);
381386
}
382387
Ok(false) => {
383-
checks.insert("github_api".into(), HealthStatus::unhealthy("Empty viewer login"));
388+
checks.insert(
389+
"github_api".into(),
390+
HealthStatus::unhealthy("Empty viewer login"),
391+
);
384392
}
385393
Err(e) => {
386394
checks.insert("github_api".into(), HealthStatus::unhealthy(e.to_string()));

0 commit comments

Comments
 (0)