Skip to content

Commit

Permalink
ci: enhance test setup and improve auto commit message generation; co…
Browse files Browse the repository at this point in the history
…nfigure git user details and refine hook script
  • Loading branch information
erguotou committed Jan 3, 2025
1 parent d47a004 commit 33e90ef
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 114 deletions.
6 changes: 4 additions & 2 deletions packages/core/__test__/index.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { init, install, runHook } from '../index.js'
const testDir = path.join(fileURLToPath(import.meta.url), '../..')

test.beforeEach('mkdir test dir', async (t) => {
execSync('git config --global user.email "[email protected]"')
execSync('git config --global user.name "Test User"')
execSync('git init')
// await fs.mkdir(testDir, { recursive: true })
// process.chdir(testDir)
await new Promise(resolve => setTimeout(resolve, 100))
console.log('Finish git init')
})
test.afterEach('rm test dir', async (t) => {
// process.chdir(startDir)
Expand Down
196 changes: 98 additions & 98 deletions packages/core/src/auto_commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,31 @@ use crate::command::run_command;
use crate::config;
use reqwest::Client;
use serde_json::json;
use spinners::{Spinner, Spinners};
use std::env;
use std::process::{Command, Stdio};
use spinners::{Spinner, Spinners};

pub async fn generate_commit_message(commit: bool) -> Result<(), String> {
let config = config::check()?;
if !config.ai.enabled {
return Err("Auto commit is not enabled".to_string());
}
// 获取git diff内容
let diff = get_git_diff()?;
if diff.is_empty() {
return Err("No changes to commit".to_string());
}
let config = config::check()?;
if !config.ai.enabled {
return Err("Auto commit is not enabled".to_string());
}
// 获取git diff内容
let diff = get_git_diff()?;
if diff.is_empty() {
return Err("No changes to commit".to_string());
}

let api_key = config
.ai
.api_key
.or_else(|| env::var("OPENAI_API_KEY").ok())
.ok_or("API key not found")?;
let base_url = config.ai.base_url.unwrap();
let model = config.ai.model.unwrap();
let api_key = config
.ai
.api_key
.or_else(|| env::var("OPENAI_API_KEY").ok())
.ok_or("API key not found")?;
let base_url = config.ai.base_url.unwrap();
let model = config.ai.model.unwrap();

// Build prompt
let system_prompt = "You are a git commit message generator. Generate a concise, standardized commit message directly with no format wrapper based on the git diff. Focus on the overall purpose or functionality of the changes, rather than listing individual file changes. Follow these guidelines:\n\
// Build prompt
let system_prompt = "You are a git commit message generator. Generate a concise, standardized commit message directly with no format wrapper based on the git diff. Focus on the overall purpose or functionality of the changes, rather than listing individual file changes. Follow these guidelines:\n\
- **Type**: Choose one of the following: build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test.\n\
- **Scope**: Optional scope of the commit, like 'cli', 'core', 'ui', 'api', etc.\n\
- **Description**: A short one-line description starting with a present-tense verb, summarizing the overall change.\n\
Expand All @@ -45,94 +45,94 @@ pub async fn generate_commit_message(commit: bool) -> Result<(), String> {
- Focus on the high-level purpose of the commit.\n\
- Keep the description concise and meaningful.\n\
- Only include a body or footer if they add significant value.";
let system_prompt = if let Some(lang) = config.ai.respond_in {
format!(
"{}\nPlease always generate the commit message in {} language",
system_prompt, lang
)
} else {
system_prompt.to_string()
};
let system_prompt = if let Some(lang) = config.ai.respond_in {
format!(
"{}\nPlease always generate the commit message in {} language",
system_prompt, lang
)
} else {
system_prompt.to_string()
};

let messages = vec![
json!({
"role": "system",
"content": system_prompt
}),
json!({
"role": "user",
"content": diff
}),
];
let messages = vec![
json!({
"role": "system",
"content": system_prompt
}),
json!({
"role": "user",
"content": diff
}),
];

let client = Client::new();
let mut spinner = Spinner::new(Spinners::Dots, "Generating commit message...".into());
let response = client
.post(format!("{}/chat/completions", base_url))
.header("Content-Type", "application/json")
.header("Authorization", format!("Bearer {}", api_key))
.json(&json!({
"model": model,
"messages": messages,
"temperature": 0.0
}))
.send()
.await
.map_err(|e| format!("Failed to send request: {}", e))?;
let client = Client::new();
let mut spinner = Spinner::new(Spinners::Dots, "Generating commit message...".into());
let response = client
.post(format!("{}/chat/completions", base_url))
.header("Content-Type", "application/json")
.header("Authorization", format!("Bearer {}", api_key))
.json(&json!({
"model": model,
"messages": messages,
"temperature": 0.0
}))
.send()
.await
.map_err(|e| format!("Failed to send request: {}", e))?;

let response_json: serde_json::Value = response
.json()
.await
.map_err(|e| format!("Failed to parse response: {}", e))?;
let response_json: serde_json::Value = response
.json()
.await
.map_err(|e| format!("Failed to parse response: {}", e))?;

spinner.stop();
spinner.stop();

let content = response_json["choices"][0]["message"]["content"]
.as_str()
.ok_or("Invalid response format")
.map_err(|e| format!("Failed to parse response: {}", e))?
.to_string();
let content = response_json["choices"][0]["message"]["content"]
.as_str()
.ok_or("Invalid response format")
.map_err(|e| format!("Failed to parse response: {}", e))?
.to_string();

println!("{}", content);
if content.is_empty() {
return Err("No commit message generated".to_string());
}
if commit {
run_command("git", &format!("commit -m \"{}\"", content))
.map_err(|e| format!("Failed to commit: {}", e))?;
} else {
let mut ps_commit = Command::new("git")
.arg("commit")
.arg("-e")
.arg("-m")
.arg(content)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()
.unwrap();
ps_commit.wait().unwrap();
}
Ok(())
println!("{}", content);
if content.is_empty() {
return Err("No commit message generated".to_string());
}
if commit {
run_command("git", &format!("commit -m \"{}\"", content))
.map_err(|e| format!("Failed to commit: {}", e))?;
} else {
let mut ps_commit = Command::new("git")
.arg("commit")
.arg("-e")
.arg("-m")
.arg(content)
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()
.unwrap();
ps_commit.wait().unwrap();
}
Ok(())
}

fn get_git_diff() -> Result<String, String> {
let output = Command::new("git")
.args(&[
"diff",
"--staged",
"--ignore-all-space",
"--diff-algorithm=minimal",
"--function-context",
"--no-ext-diff",
"--no-color",
])
.output()
.map_err(|e| format!("Failed to get git diff: {}", e))?;
let output = Command::new("git")
.args(&[
"diff",
"--staged",
"--ignore-all-space",
"--diff-algorithm=minimal",
"--function-context",
"--no-ext-diff",
"--no-color",
])
.output()
.map_err(|e| format!("Failed to get git diff: {}", e))?;

if !output.status.success() {
return Err("Git diff command failed".to_string());
}
if !output.status.success() {
return Err("Git diff command failed".to_string());
}

Ok(String::from_utf8_lossy(&output.stdout).to_string())
Ok(String::from_utf8_lossy(&output.stdout).to_string())
}
16 changes: 2 additions & 14 deletions packages/core/src/hooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,10 @@ pub fn install() -> Result<(), Box<dyn Error>> {
// generate hooks
for hook_name in hooks.iter() {
let hook_path = hooks_dir.join(hook_name);
let bin_entry_path = Path::new("./node_modules/@doremijs/igit-cli/bin/index.mjs");
let hook_content = format!(
r#"#!/bin/sh
run_command() {{
if command -v bun > /dev/null 2>&1; then
bun "$@"
elif command -v deno > /dev/null 2>&1; then
deno run "$@"
else
node "$@"
fi
}}
run_command {} run "{}" "$@"
r#"#!/usr/bin/env sh
npx igit run "{}" "$@"
"#,
bin_entry_path.to_string_lossy(),
hook_name
);
fs::write(&hook_path, hook_content)?;
Expand Down

0 comments on commit 33e90ef

Please sign in to comment.