devgen-cli 0.2.1__py3-none-any.whl → 0.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- devgen/cli/commit.py +1 -1
- devgen/modules/changelog_generator.py +8 -20
- devgen/modules/commit_generator.py +101 -50
- devgen/providers/__init__.py +10 -7
- devgen/providers/openai.py +3 -0
- devgen/providers/openrouter.py +3 -0
- devgen/utils.py +47 -8
- devgen_cli-0.2.3.dist-info/METADATA +177 -0
- {devgen_cli-0.2.1.dist-info → devgen_cli-0.2.3.dist-info}/RECORD +13 -13
- devgen_cli-0.2.1.dist-info/METADATA +0 -299
- {devgen_cli-0.2.1.dist-info → devgen_cli-0.2.3.dist-info}/WHEEL +0 -0
- {devgen_cli-0.2.1.dist-info → devgen_cli-0.2.3.dist-info}/entry_points.txt +0 -0
- {devgen_cli-0.2.1.dist-info → devgen_cli-0.2.3.dist-info}/licenses/LICENSE +0 -0
- {devgen_cli-0.2.1.dist-info → devgen_cli-0.2.3.dist-info}/top_level.txt +0 -0
devgen/cli/commit.py
CHANGED
|
@@ -52,7 +52,7 @@ def run_commit(
|
|
|
52
52
|
] = False,
|
|
53
53
|
) -> None:
|
|
54
54
|
log_file = get_main_log_path()
|
|
55
|
-
logger = configure_logger("devgen.cli.commit", log_file)
|
|
55
|
+
logger = configure_logger("devgen.cli.commit", log_file, console=debug)
|
|
56
56
|
logger.info(f"Log file: {log_file}")
|
|
57
57
|
logger.info(
|
|
58
58
|
f"Options: dry_run={dry_run}, push={push}, debug={debug}, force={force_rebuild}"
|
|
@@ -5,7 +5,7 @@ from datetime import datetime
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Dict, List, Optional
|
|
7
7
|
|
|
8
|
-
from devgen.utils import configure_logger
|
|
8
|
+
from devgen.utils import configure_logger, run_git_command
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class ChangelogGenerator:
|
|
@@ -14,22 +14,6 @@ class ChangelogGenerator:
|
|
|
14
14
|
def __init__(self, logger=None):
|
|
15
15
|
self.logger = logger or configure_logger("devgen.changelog")
|
|
16
16
|
|
|
17
|
-
def _exec_git(self, args: List[str]) -> str:
|
|
18
|
-
"""Executes a git command."""
|
|
19
|
-
try:
|
|
20
|
-
res = subprocess.run(
|
|
21
|
-
args,
|
|
22
|
-
capture_output=True,
|
|
23
|
-
text=True,
|
|
24
|
-
encoding="utf-8",
|
|
25
|
-
errors="replace",
|
|
26
|
-
check=True,
|
|
27
|
-
)
|
|
28
|
-
return res.stdout.strip()
|
|
29
|
-
except subprocess.CalledProcessError as e:
|
|
30
|
-
self.logger.error(f"Git command failed: {e}")
|
|
31
|
-
raise RuntimeError(f"Git command failed: {e}")
|
|
32
|
-
|
|
33
17
|
def get_commits(self, from_ref: str = "", to_ref: str = "HEAD") -> List[str]:
|
|
34
18
|
"""Fetches commit messages in the specified range."""
|
|
35
19
|
range_spec = f"{from_ref}..{to_ref}" if from_ref else to_ref
|
|
@@ -40,7 +24,7 @@ class ChangelogGenerator:
|
|
|
40
24
|
if not from_ref:
|
|
41
25
|
# If no start ref, try to find the last tag
|
|
42
26
|
try:
|
|
43
|
-
last_tag =
|
|
27
|
+
last_tag = run_git_command(["git", "describe", "--tags", "--abbrev=0"])
|
|
44
28
|
cmd = [
|
|
45
29
|
"git",
|
|
46
30
|
"log",
|
|
@@ -49,11 +33,15 @@ class ChangelogGenerator:
|
|
|
49
33
|
f"{last_tag}..HEAD",
|
|
50
34
|
]
|
|
51
35
|
self.logger.info(f"Generating changelog from last tag: {last_tag}")
|
|
52
|
-
except RuntimeError:
|
|
36
|
+
except (RuntimeError, subprocess.CalledProcessError):
|
|
53
37
|
self.logger.info("No tags found, generating for all commits.")
|
|
54
38
|
cmd = ["git", "log", f"--format={fmt}", "--date=short"]
|
|
55
39
|
|
|
56
|
-
|
|
40
|
+
try:
|
|
41
|
+
return run_git_command(cmd).split("\n")
|
|
42
|
+
except subprocess.CalledProcessError as e:
|
|
43
|
+
self.logger.error(f"Git command failed: {e}")
|
|
44
|
+
raise RuntimeError(f"Git command failed: {e}")
|
|
57
45
|
|
|
58
46
|
def parse_commits(self, raw_commits: List[str]) -> Dict[str, List[Dict]]:
|
|
59
47
|
"""Parses raw commit strings into structured data."""
|
|
@@ -11,8 +11,13 @@ from devgen.utils import (
|
|
|
11
11
|
get_commit_dry_run_path,
|
|
12
12
|
is_file_recent,
|
|
13
13
|
load_template_env,
|
|
14
|
+
run_git_command,
|
|
14
15
|
sanitize_ai_commit_message,
|
|
15
16
|
)
|
|
17
|
+
from rich.console import Console
|
|
18
|
+
from rich.panel import Panel
|
|
19
|
+
from rich.markdown import Markdown
|
|
20
|
+
from rich.theme import Theme
|
|
16
21
|
|
|
17
22
|
|
|
18
23
|
class CommitEngineError(Exception):
|
|
@@ -45,48 +50,44 @@ class CommitEngine:
|
|
|
45
50
|
self.provider = provider
|
|
46
51
|
self.model = model
|
|
47
52
|
self.logger = logger or configure_logger(
|
|
48
|
-
"devgen.commit",
|
|
53
|
+
"devgen.commit",
|
|
54
|
+
Path.home() / ".cache" / "devgen" / "commit.log",
|
|
55
|
+
console=debug,
|
|
49
56
|
)
|
|
50
57
|
self.kwargs = kwargs
|
|
51
58
|
self.dry_run_path = get_commit_dry_run_path()
|
|
52
59
|
self.template_env = load_template_env("commit")
|
|
53
60
|
|
|
61
|
+
self.console = Console(
|
|
62
|
+
theme=Theme(
|
|
63
|
+
{"info": "dim cyan", "warning": "magenta", "danger": "bold red"}
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
54
67
|
# Load config from ~/.devgen.yaml
|
|
55
68
|
from devgen.utils import load_config
|
|
56
69
|
|
|
57
70
|
self.config = load_config()
|
|
58
71
|
|
|
59
|
-
def
|
|
60
|
-
"""
|
|
72
|
+
def detect_changes(self) -> List[str]:
|
|
73
|
+
"""Detects changed, deleted, or untracked files."""
|
|
61
74
|
try:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
out = run_git_command(
|
|
76
|
+
[
|
|
77
|
+
"git",
|
|
78
|
+
"ls-files",
|
|
79
|
+
"--deleted",
|
|
80
|
+
"--modified",
|
|
81
|
+
"--others",
|
|
82
|
+
"--exclude-standard",
|
|
83
|
+
]
|
|
69
84
|
)
|
|
70
|
-
return
|
|
85
|
+
return [f.strip() for f in out.split("\n") if f.strip()]
|
|
71
86
|
except subprocess.CalledProcessError as e:
|
|
72
87
|
msg = f"Git command failed: {' '.join(e.cmd)}\nError: {e.stderr.strip()}"
|
|
73
88
|
self.logger.error(msg)
|
|
74
89
|
raise CommitEngineError(msg) from e
|
|
75
90
|
|
|
76
|
-
def detect_changes(self) -> List[str]:
|
|
77
|
-
"""Detects changed, deleted, or untracked files."""
|
|
78
|
-
out = self._exec_git(
|
|
79
|
-
[
|
|
80
|
-
"git",
|
|
81
|
-
"ls-files",
|
|
82
|
-
"--deleted",
|
|
83
|
-
"--modified",
|
|
84
|
-
"--others",
|
|
85
|
-
"--exclude-standard",
|
|
86
|
-
]
|
|
87
|
-
)
|
|
88
|
-
return [f.strip() for f in out.split("\n") if f.strip()]
|
|
89
|
-
|
|
90
91
|
def group_files(self, files: List[str]) -> Dict[str, List[str]]:
|
|
91
92
|
"""Groups files by their parent directory."""
|
|
92
93
|
groups = defaultdict(list)
|
|
@@ -98,7 +99,14 @@ class CommitEngine:
|
|
|
98
99
|
|
|
99
100
|
def generate_diff(self, files: List[str]) -> str:
|
|
100
101
|
"""Generates diff for specific files."""
|
|
101
|
-
|
|
102
|
+
try:
|
|
103
|
+
return run_git_command(
|
|
104
|
+
["git", "--no-pager", "diff", "--staged", "--", *files]
|
|
105
|
+
)
|
|
106
|
+
except subprocess.CalledProcessError as e:
|
|
107
|
+
msg = f"Git command failed: {' '.join(e.cmd)}\nError: {e.stderr.strip()}"
|
|
108
|
+
self.logger.error(msg)
|
|
109
|
+
raise CommitEngineError(msg) from e
|
|
102
110
|
|
|
103
111
|
def _init_dry_run(self):
|
|
104
112
|
"""Initializes the dry-run file."""
|
|
@@ -108,7 +116,15 @@ class CommitEngine:
|
|
|
108
116
|
f.write(f"# Dry Run: Commit Messages\n_Generated: {ts}_\n\n")
|
|
109
117
|
|
|
110
118
|
def _log_dry_run(self, group: str, msg: str):
|
|
111
|
-
"""Appends a dry-run entry."""
|
|
119
|
+
"""Appends a dry-run entry and prints to console."""
|
|
120
|
+
self.console.print(
|
|
121
|
+
Panel(
|
|
122
|
+
Markdown(msg),
|
|
123
|
+
title=f"Dry Run: {group}",
|
|
124
|
+
border_style="yellow",
|
|
125
|
+
expand=False,
|
|
126
|
+
)
|
|
127
|
+
)
|
|
112
128
|
with self.dry_run_path.open("a", encoding="utf-8") as f:
|
|
113
129
|
f.write(f"## Group: `{group}`\n\n```md\n{msg}\n```\n\n---\n\n")
|
|
114
130
|
|
|
@@ -117,18 +133,40 @@ class CommitEngine:
|
|
|
117
133
|
if not files:
|
|
118
134
|
return
|
|
119
135
|
self.logger.info(f"Staging: {files}")
|
|
120
|
-
self.
|
|
136
|
+
self.console.print(f"[info]Staging {len(files)} files...[/info]")
|
|
137
|
+
try:
|
|
138
|
+
run_git_command(["git", "add", *files])
|
|
139
|
+
except subprocess.CalledProcessError as e:
|
|
140
|
+
msg = f"Git command failed: {' '.join(e.cmd)}\nError: {e.stderr.strip()}"
|
|
141
|
+
self.logger.error(msg)
|
|
142
|
+
raise CommitEngineError(msg) from e
|
|
121
143
|
|
|
122
144
|
def commit_staged(self, msg: str):
|
|
123
145
|
"""Commits staged changes."""
|
|
124
146
|
self.logger.info(f"Committing:\n{msg}")
|
|
125
|
-
self.
|
|
147
|
+
self.console.print(
|
|
148
|
+
Panel(Markdown(msg), title="Commit Message", border_style="green")
|
|
149
|
+
)
|
|
150
|
+
try:
|
|
151
|
+
run_git_command(["git", "commit", "-m", msg])
|
|
152
|
+
except subprocess.CalledProcessError as e:
|
|
153
|
+
msg = f"Git command failed: {' '.join(e.cmd)}\nError: {e.stderr.strip()}"
|
|
154
|
+
self.logger.error(msg)
|
|
155
|
+
raise CommitEngineError(msg) from e
|
|
126
156
|
|
|
127
157
|
def push_commits(self):
|
|
128
158
|
"""Pushes commits to remote."""
|
|
129
159
|
self.logger.info("Pushing to remote...")
|
|
130
|
-
self.
|
|
131
|
-
|
|
160
|
+
with self.console.status("[bold green]Pushing to remote...[/bold green]"):
|
|
161
|
+
try:
|
|
162
|
+
run_git_command(["git", "push"])
|
|
163
|
+
except subprocess.CalledProcessError as e:
|
|
164
|
+
msg = (
|
|
165
|
+
f"Git command failed: {' '.join(e.cmd)}\nError: {e.stderr.strip()}"
|
|
166
|
+
)
|
|
167
|
+
self.logger.error(msg)
|
|
168
|
+
raise CommitEngineError(msg) from e
|
|
169
|
+
self.console.print("[bold green]Push successful.[/bold green]")
|
|
132
170
|
|
|
133
171
|
def generate_message(self, group: str, diff: str, cache: Dict[str, str]) -> str:
|
|
134
172
|
"""Generates a commit message using AI or cache."""
|
|
@@ -147,28 +185,32 @@ class CommitEngine:
|
|
|
147
185
|
template = self.template_env.get_template("commit_message.j2")
|
|
148
186
|
prompt = template.render(group_name=group, diff_text=diff, use_emoji=use_emoji)
|
|
149
187
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
188
|
+
with self.console.status("[bold blue]Generating commit message...[/bold blue]"):
|
|
189
|
+
raw = generate_with_ai(
|
|
190
|
+
prompt,
|
|
191
|
+
provider=provider,
|
|
192
|
+
model=model,
|
|
193
|
+
api_key=api_key,
|
|
194
|
+
debug=self.debug,
|
|
195
|
+
**self.kwargs,
|
|
196
|
+
)
|
|
158
197
|
return sanitize_ai_commit_message(raw)
|
|
159
198
|
|
|
160
199
|
def is_ahead_of_remote(self) -> bool:
|
|
161
200
|
"""Checks if local branch has unpushed commits."""
|
|
162
201
|
try:
|
|
163
|
-
|
|
164
|
-
count =
|
|
165
|
-
["git", "rev-list", "--count", "@{u}..HEAD"],
|
|
202
|
+
run_git_command(["git", "fetch", "origin"])
|
|
203
|
+
count = run_git_command(
|
|
204
|
+
["git", "rev-list", "--count", "@{u}..HEAD"], check=False
|
|
166
205
|
)
|
|
167
206
|
if count and int(count) > 0:
|
|
168
207
|
return True
|
|
169
|
-
except CommitEngineError:
|
|
208
|
+
except (subprocess.CalledProcessError, CommitEngineError):
|
|
170
209
|
# Maybe no upstream
|
|
171
|
-
|
|
210
|
+
try:
|
|
211
|
+
return bool(run_git_command(["git", "rev-parse", "HEAD"], check=False))
|
|
212
|
+
except subprocess.CalledProcessError:
|
|
213
|
+
return False
|
|
172
214
|
return False
|
|
173
215
|
|
|
174
216
|
def load_cache(self) -> Dict[str, str]:
|
|
@@ -190,7 +232,10 @@ class CommitEngine:
|
|
|
190
232
|
|
|
191
233
|
if not diff.strip():
|
|
192
234
|
self.logger.info(f"Skipping empty diff for {group}")
|
|
193
|
-
|
|
235
|
+
try:
|
|
236
|
+
run_git_command(["git", "reset", "HEAD", "--", *files])
|
|
237
|
+
except subprocess.CalledProcessError:
|
|
238
|
+
pass # Ignore reset errors
|
|
194
239
|
return True
|
|
195
240
|
|
|
196
241
|
msg = self.generate_message(group, diff, cache)
|
|
@@ -200,7 +245,10 @@ class CommitEngine:
|
|
|
200
245
|
|
|
201
246
|
if self.dry_run:
|
|
202
247
|
self._log_dry_run(group, msg)
|
|
203
|
-
|
|
248
|
+
try:
|
|
249
|
+
run_git_command(["git", "reset", "HEAD", "--", *files])
|
|
250
|
+
except subprocess.CalledProcessError:
|
|
251
|
+
pass
|
|
204
252
|
else:
|
|
205
253
|
self.commit_staged(msg)
|
|
206
254
|
|
|
@@ -237,16 +285,19 @@ class CommitEngine:
|
|
|
237
285
|
self.logger.error("Push aborted due to failed commits.")
|
|
238
286
|
|
|
239
287
|
if self.dry_run:
|
|
240
|
-
self.
|
|
288
|
+
self.console.print(
|
|
289
|
+
f"[bold green]Dry run done.[/bold green] See {self.dry_run_path}"
|
|
290
|
+
)
|
|
241
291
|
else:
|
|
242
|
-
self.
|
|
292
|
+
self.console.print("[bold green]Done.[/bold green]")
|
|
243
293
|
if failed:
|
|
244
|
-
self.
|
|
294
|
+
self.console.print(f"[bold red]Failed groups: {failed}[/bold red]")
|
|
245
295
|
|
|
246
296
|
|
|
247
297
|
def run_commit_engine(**kwargs):
|
|
248
298
|
"""Entry point for the commit engine."""
|
|
249
|
-
|
|
299
|
+
debug = kwargs.get("debug", False)
|
|
300
|
+
logger = configure_logger("devgen.commit", console=debug)
|
|
250
301
|
try:
|
|
251
302
|
engine = CommitEngine(**kwargs)
|
|
252
303
|
engine.execute()
|
devgen/providers/__init__.py
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
|
-
from devgen.providers.anthropic import AnthropicProvider
|
|
2
|
-
from devgen.providers.gemini import GeminiProvider
|
|
3
|
-
from devgen.providers.huggingface import HuggingfaceProvider
|
|
4
|
-
from devgen.providers.openai import OpenaiProvider
|
|
5
|
-
from devgen.providers.openrouter import OpenrouterProvider
|
|
6
|
-
|
|
7
|
-
|
|
8
1
|
def get_provider(name):
|
|
9
2
|
name_lower = name.lower()
|
|
10
3
|
if name_lower == "gemini":
|
|
4
|
+
from devgen.providers.gemini import GeminiProvider
|
|
5
|
+
|
|
11
6
|
return GeminiProvider()
|
|
12
7
|
elif name_lower == "openai":
|
|
8
|
+
from devgen.providers.openai import OpenaiProvider
|
|
9
|
+
|
|
13
10
|
return OpenaiProvider()
|
|
14
11
|
elif name_lower == "huggingface":
|
|
12
|
+
from devgen.providers.huggingface import HuggingfaceProvider
|
|
13
|
+
|
|
15
14
|
return HuggingfaceProvider()
|
|
16
15
|
elif name_lower == "openrouter":
|
|
16
|
+
from devgen.providers.openrouter import OpenrouterProvider
|
|
17
|
+
|
|
17
18
|
return OpenrouterProvider()
|
|
18
19
|
elif name_lower == "anthropic":
|
|
20
|
+
from devgen.providers.anthropic import AnthropicProvider
|
|
21
|
+
|
|
19
22
|
return AnthropicProvider()
|
|
20
23
|
|
|
21
24
|
raise NotImplementedError(f"Provider '{name}' is not implemented yet.")
|
devgen/providers/openai.py
CHANGED
|
@@ -39,6 +39,9 @@ class OpenaiProvider:
|
|
|
39
39
|
# Add error handling if the client fails to initialize
|
|
40
40
|
raise RuntimeError(f"Failed to initialize OpenAI client: {e}")
|
|
41
41
|
|
|
42
|
+
# Remove debug from kwargs if present
|
|
43
|
+
kwargs.pop("debug", None)
|
|
44
|
+
|
|
42
45
|
# 2. Use the modern API syntax: client.chat.completions.create
|
|
43
46
|
response = client.chat.completions.create(
|
|
44
47
|
model=model or self.DEFAULT_MODEL,
|
devgen/providers/openrouter.py
CHANGED
devgen/utils.py
CHANGED
|
@@ -75,7 +75,7 @@ def extract_commit_messages(filepath: Path | str) -> dict[str, str]:
|
|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
def configure_logger(
|
|
78
|
-
name: str = "devgen", log_file: Optional[Path | str] = None
|
|
78
|
+
name: str = "devgen", log_file: Optional[Path | str] = None, console: bool = True
|
|
79
79
|
) -> logging.Logger:
|
|
80
80
|
logger = logging.getLogger(name)
|
|
81
81
|
logger.setLevel(logging.INFO)
|
|
@@ -88,9 +88,10 @@ def configure_logger(
|
|
|
88
88
|
)
|
|
89
89
|
|
|
90
90
|
# Console handler
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
if console:
|
|
92
|
+
ch = logging.StreamHandler()
|
|
93
|
+
ch.setFormatter(formatter)
|
|
94
|
+
logger.addHandler(ch)
|
|
94
95
|
|
|
95
96
|
# File handler
|
|
96
97
|
if log_file:
|
|
@@ -103,15 +104,52 @@ def configure_logger(
|
|
|
103
104
|
return logger
|
|
104
105
|
|
|
105
106
|
|
|
106
|
-
def
|
|
107
|
+
def run_git_command(
|
|
108
|
+
args: list[str],
|
|
109
|
+
check: bool = True,
|
|
110
|
+
cwd: Optional[Path] = None,
|
|
111
|
+
encoding: str = "utf-8",
|
|
112
|
+
errors: str = "replace",
|
|
113
|
+
) -> str:
|
|
114
|
+
"""
|
|
115
|
+
Executes a git command and returns the output.
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
args: List of command arguments (e.g., ["git", "status"]).
|
|
119
|
+
check: Whether to raise an exception on non-zero exit code.
|
|
120
|
+
cwd: Current working directory for the command.
|
|
121
|
+
encoding: Output encoding.
|
|
122
|
+
errors: Error handling strategy for encoding.
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
The standard output of the command, stripped of leading/trailing whitespace.
|
|
126
|
+
|
|
127
|
+
Raises:
|
|
128
|
+
subprocess.CalledProcessError: If the command fails and check is True.
|
|
129
|
+
"""
|
|
107
130
|
try:
|
|
108
131
|
res = subprocess.run(
|
|
109
|
-
|
|
132
|
+
args,
|
|
110
133
|
capture_output=True,
|
|
111
134
|
text=True,
|
|
112
|
-
|
|
135
|
+
encoding=encoding,
|
|
136
|
+
errors=errors,
|
|
137
|
+
check=check,
|
|
138
|
+
cwd=cwd,
|
|
113
139
|
)
|
|
114
|
-
return
|
|
140
|
+
return res.stdout.strip()
|
|
141
|
+
except subprocess.CalledProcessError as e:
|
|
142
|
+
# Log the error if a logger is configured, but re-raise
|
|
143
|
+
# We don't have access to a specific logger here easily without passing it in,
|
|
144
|
+
# so we rely on the caller to handle logging if needed, or we could log to a default one.
|
|
145
|
+
# For now, just re-raise as the caller expects.
|
|
146
|
+
raise e
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_git_staged_files() -> list[str]:
|
|
150
|
+
try:
|
|
151
|
+
output = run_git_command(["git", "diff", "--name-only", "--cached"])
|
|
152
|
+
return [f for f in output.splitlines() if f.strip()]
|
|
115
153
|
except subprocess.CalledProcessError:
|
|
116
154
|
return []
|
|
117
155
|
|
|
@@ -170,6 +208,7 @@ __all__ = [
|
|
|
170
208
|
"sanitize_ai_commit_message",
|
|
171
209
|
"extract_commit_messages",
|
|
172
210
|
"configure_logger",
|
|
211
|
+
"run_git_command",
|
|
173
212
|
"get_git_staged_files",
|
|
174
213
|
"read_file_content",
|
|
175
214
|
"delete_file",
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devgen-cli
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Summary: A collection of developer tools
|
|
5
|
+
Home-page: https://github.com/S4NKALP/devgen
|
|
6
|
+
Author: Sankalp Tharu
|
|
7
|
+
Author-email: Sankalp Tharu <sankalptharu50028@gmail.com>
|
|
8
|
+
License: GPL-3.0-or-later
|
|
9
|
+
Project-URL: Homepage, https://github.com/S4NKALP/devgen
|
|
10
|
+
Keywords: devgen,cli,git,changelog,gitignore,license,commit-generator,commit
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: anthropic>=0.75.0
|
|
24
|
+
Requires-Dist: google-generativeai>=0.8.5
|
|
25
|
+
Requires-Dist: jinja2>=3.1.6
|
|
26
|
+
Requires-Dist: openai>=2.11.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0.3
|
|
28
|
+
Requires-Dist: questionary>=2.1.1
|
|
29
|
+
Requires-Dist: requests>=2.32.5
|
|
30
|
+
Requires-Dist: rich>=14.2.0
|
|
31
|
+
Requires-Dist: toml>=0.10.2
|
|
32
|
+
Requires-Dist: typer>=0.20.0
|
|
33
|
+
Dynamic: author
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: requires-python
|
|
37
|
+
|
|
38
|
+
# DevGen
|
|
39
|
+
|
|
40
|
+
<div align="center">
|
|
41
|
+
|
|
42
|
+
> **Your AI Powerhouse for Git & Project Management.**
|
|
43
|
+
> Stop wasting time on repetitive tasks. Automate your commits, changelogs, and project essentials with a single CLI.
|
|
44
|
+
>
|
|
45
|
+
> PyPI didn't allow the original name, so you'll find it as **devgen-cli** on PyPI
|
|
46
|
+
|
|
47
|
+
<a href="https://pypi.org/project/devgen-cli"><img src="https://img.shields.io/pypi/v/devgen-cli?color=blue&label=PyPI&logo=pypi&logoColor=white" alt="PyPI"></a>
|
|
48
|
+
<img src="https://img.shields.io/badge/Python-3.10%2B-3776AB?logo=python&logoColor=white" alt="Python">
|
|
49
|
+
<a href="https://github.com/S4NKALP/DevGen/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-GPL--3.0--or--later-blue.svg" alt="License"></a>
|
|
50
|
+
|
|
51
|
+
</div>
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
**DevGen** isn't just another CLI tool it's your development workflow on steroids. By leveraging state of the art AI models, DevGen turns tedious manual tasks into one click magic. From semantic commit messages to comprehensive release notes, DevGen handles the boring stuff so you can focus on building.
|
|
56
|
+
|
|
57
|
+
## ⚡ Why DevGen?
|
|
58
|
+
|
|
59
|
+
**🧠 AI Brain**
|
|
60
|
+
Semantic commit messages powered by Gemini, OpenAI, Claude, HuggingFace, and OpenRouter. It reads your diffs and understands your code.
|
|
61
|
+
|
|
62
|
+
**🚀 Battle Tested**
|
|
63
|
+
Generates **Conventional Commits** and **Semantic Versioning** compliant changelogs that actually make sense.
|
|
64
|
+
|
|
65
|
+
**⚡ Lightning Fast**
|
|
66
|
+
Smart caching and async operations mean you never wait longer than necessary.
|
|
67
|
+
|
|
68
|
+
**Project Essentials**
|
|
69
|
+
Quickly add `.gitignore` and license files to your existing projects. Access cached templates instantly, even without internet.
|
|
70
|
+
|
|
71
|
+
**🛠️ Zero Friction**
|
|
72
|
+
Interactive setup gets you running in seconds.
|
|
73
|
+
|
|
74
|
+
## 📦 Installation
|
|
75
|
+
|
|
76
|
+
Get started in seconds.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Recommended: Install via pipx for an isolated environment
|
|
80
|
+
pipx install devgen-cli
|
|
81
|
+
|
|
82
|
+
# Or use uv for blazing speed
|
|
83
|
+
uv tool install devgen-cli
|
|
84
|
+
|
|
85
|
+
# Standard pip install
|
|
86
|
+
pip install devgen-cli
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## 🚀 Quick Start
|
|
90
|
+
|
|
91
|
+
**1. Initialize & Configure**
|
|
92
|
+
Tell DevGen which AI provider to use.
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
devgen setup config
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
**2. Stage & Commit**
|
|
99
|
+
Stage your files and let AI write the message.
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
git add .
|
|
103
|
+
devgen commit run
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
_Boom. Done._
|
|
107
|
+
|
|
108
|
+
## 💡 Feature Deep Dive
|
|
109
|
+
|
|
110
|
+
### 🤖 AI Powered Commits
|
|
111
|
+
|
|
112
|
+
Stop writing "fix bug" or "wip". DevGen analyzes your staged changes, groups them by component, and generates meaningful, semantic commit messages.
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# Preview what DevGen will generate
|
|
116
|
+
devgen commit run --dry-run
|
|
117
|
+
|
|
118
|
+
# Commit and push in one go
|
|
119
|
+
devgen commit run --push
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 📝 Changelogs & Release Notes
|
|
123
|
+
|
|
124
|
+
Turn your git history into beautiful, readable documentation.
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
# Generate a changelog from the last tag
|
|
128
|
+
devgen changelog generate
|
|
129
|
+
|
|
130
|
+
# Create release notes for v2.0.0
|
|
131
|
+
devgen release notes --version 2.0.0
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 🛡️ Essential Files
|
|
135
|
+
|
|
136
|
+
Don't waste time searching for templates. Generate the essential files for your project instantly.
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
# Interactive search for gitignore templates
|
|
140
|
+
devgen gitignore generate
|
|
141
|
+
|
|
142
|
+
# Generate a license interactively
|
|
143
|
+
devgen license generate
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## ⚙️ Configuration
|
|
147
|
+
|
|
148
|
+
Your settings live in `~/.devgen.yaml`. You can tweak your AI provider, model, and preferences there.
|
|
149
|
+
|
|
150
|
+
| Option | Description |
|
|
151
|
+
| :--------- | :----------------------------------------------------------- |
|
|
152
|
+
| `provider` | `gemini`, `openai`, `anthropic`, `huggingface`, `openrouter` |
|
|
153
|
+
| `model` | Specific model name (e.g., `gemini-2.5-flash`, `gpt-4o`) |
|
|
154
|
+
| `emoji` | Enable/disable gitmojis in commits (`true`/`false`) |
|
|
155
|
+
|
|
156
|
+
## 🤝 Contributing
|
|
157
|
+
|
|
158
|
+
We love contributions! Found a bug? Want a new feature? Open an issue or submit a PR.
|
|
159
|
+
|
|
160
|
+
## � Acknowledgments
|
|
161
|
+
|
|
162
|
+
DevGen wouldn't be possible without these amazing open-source projects and AI providers:
|
|
163
|
+
|
|
164
|
+
- **[Typer](https://typer.tiangolo.com/)** & **[Rich](https://rich.readthedocs.io/)** for building the beautiful, intuitive, and responsive CLI interface.
|
|
165
|
+
- **[Questionary](https://github.com/tmbo/questionary)** for creating interactive, user-friendly prompts and selection menus.
|
|
166
|
+
- **[Jinja2](https://jinja.palletsprojects.com/)** for the powerful template engine used to generate files and messages.
|
|
167
|
+
- **[Google Gemini](https://deepmind.google/technologies/gemini/)**, **[OpenAI](https://openai.com/)**, **[Anthropic](https://www.anthropic.com/)**, **[HuggingFace](https://huggingface.co/)**, and **[OpenRouter](https://openrouter.ai/)** for providing the advanced AI models that power the semantic generation features.
|
|
168
|
+
|
|
169
|
+
## �📝 License
|
|
170
|
+
|
|
171
|
+
Proudly open source under the [GPL-3.0-or-later](LICENSE) License.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
<div align="center">
|
|
176
|
+
Made with ❤️ by <a href="https://github.com/S4NKALP">Sankalp</a>
|
|
177
|
+
</div>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
devgen/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
devgen/ai.py,sha256=e4aVFfa1atwmIBI9QSot4EnEiDG9SBwtGOMx91mh1ow,1494
|
|
3
|
-
devgen/utils.py,sha256=
|
|
3
|
+
devgen/utils.py,sha256=l2mFzKD5nuF3DPZ7ORPQINboROwQiHCVS3YgqZOrac0,6857
|
|
4
4
|
devgen/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
devgen/cli/changelog.py,sha256=V8HhhzsIcI0CZQnJeUv06Zns4oCVS51ndFsnQC78HZ8,960
|
|
6
|
-
devgen/cli/commit.py,sha256=
|
|
6
|
+
devgen/cli/commit.py,sha256=MhEXxRKXYB1v9MmHjwZ7XCEb9G2Hn5Dv33VSOEQ5KHU,2475
|
|
7
7
|
devgen/cli/config.py,sha256=l1ip4Rw7k1rph3HIxT9rXF0WTUecP_ptUfy2-aC6JKI,4960
|
|
8
8
|
devgen/cli/gitignore.py,sha256=Nl7t_EZDhsOs5y-YkbOiuFLxHuAw48QTpw4_m9qJR2w,4446
|
|
9
9
|
devgen/cli/license.py,sha256=LAwro2Mwf7PEQWORMFqwp__Mn0Kx3BPhqZR-ttuKAbk,2830
|
|
@@ -11,17 +11,17 @@ devgen/cli/main.py,sha256=xmuZH3m7ckl14fjTnjtys65MD_aXA2JW4jjo0vfmZaQ,3356
|
|
|
11
11
|
devgen/cli/release.py,sha256=X0PfH7Vx__-CraiCNoMvxXWDmcmKdCdX16TYNubteV4,864
|
|
12
12
|
devgen/cli/setup.py,sha256=LOxYkjHDYQIwIOv7N4VJRek6QyU_pqk7B_R3qArjOm0,2477
|
|
13
13
|
devgen/modules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
|
-
devgen/modules/changelog_generator.py,sha256
|
|
15
|
-
devgen/modules/commit_generator.py,sha256=
|
|
14
|
+
devgen/modules/changelog_generator.py,sha256=-3kT-nxw2MCIGbGtg-k7tsd6RsdJi5TAVqVQ5eU7Rvg,6489
|
|
15
|
+
devgen/modules/commit_generator.py,sha256=6hJG9uyNB2Y0MXx2VdxQ0mmBYI3zVLYMSfFpskym_Yk,10833
|
|
16
16
|
devgen/modules/gitignore_generator.py,sha256=DpHAOrKIwSDklv7CLelYro478MQGJ4EcMAFi5E--348,4379
|
|
17
17
|
devgen/modules/license_generator.py,sha256=nOWcyPKgMnjHIYmu6CwZ-teDr_nl0j1lWpouuMjqDQg,2665
|
|
18
18
|
devgen/modules/release_note_generator.py,sha256=IiVNHV6KdpTjPCJCxuYKLWX_pVc-2ORuh82OQwZBVWg,2112
|
|
19
|
-
devgen/providers/__init__.py,sha256=
|
|
19
|
+
devgen/providers/__init__.py,sha256=44ibMNiWX5IOm37_uTgX4OGLsUWGAlmzALF7uKOn7T8,802
|
|
20
20
|
devgen/providers/anthropic.py,sha256=IeOwQTLcemOlSLAHAu7MPQVoAK2ZvjixzKuKKNq2nqs,782
|
|
21
21
|
devgen/providers/gemini.py,sha256=xrFo5vMTCpWjg2eUaLDygDc949K1-esp31rMSsIUZEY,792
|
|
22
22
|
devgen/providers/huggingface.py,sha256=bJjna6XDcjSWb6E-RZOYzSjP8ea5X5_zjCQAekF1iIc,1575
|
|
23
|
-
devgen/providers/openai.py,sha256=
|
|
24
|
-
devgen/providers/openrouter.py,sha256=
|
|
23
|
+
devgen/providers/openai.py,sha256=e92AMNles5yZeDnTQHcWcqAvH-p-10Ptqxbcwuz9pWA,2254
|
|
24
|
+
devgen/providers/openrouter.py,sha256=Cnu8A9hwjiWzL_s2dwXbQDbhRqqXqlcnGTyqxqZKhLQ,1196
|
|
25
25
|
devgen/templates/commit/commit_message.j2,sha256=gTECP-5V5rAwCpg3gT7SsLAMT9AnSibC8vHXDe80yR4,793
|
|
26
26
|
devgen/templates/licenses/agpl-3.0.json,sha256=lYJObhc3-nBQQD2L3cw9C-Q9ceiV26qkzp6b1H7NnZ4,35832
|
|
27
27
|
devgen/templates/licenses/apache-2.0.json,sha256=7U9zUdz8kbmrtL0hDgOgtYMhRnA7Qi7WuDxSMNQ0MIU,11989
|
|
@@ -36,9 +36,9 @@ devgen/templates/licenses/lgpl-2.1.json,sha256=M1uxVajrZBccW3gX5cYwMdZ0DyBLbxnmP
|
|
|
36
36
|
devgen/templates/licenses/mit.json,sha256=NfRzL86O8TZOY2ZRdelQFEVX0t1o3bUJtqmib-pXM0s,1426
|
|
37
37
|
devgen/templates/licenses/mpl-2.0.json,sha256=Fq-oj2-z5TZS2Qr9bQHea-Nm_baC2_7DQtuSKT476Yk,17729
|
|
38
38
|
devgen/templates/licenses/unlicense.json,sha256=uWl_NnBn_Daqu-0df7y4E5H0q7KUdDby3TK1IHBDr4Y,1553
|
|
39
|
-
devgen_cli-0.2.
|
|
40
|
-
devgen_cli-0.2.
|
|
41
|
-
devgen_cli-0.2.
|
|
42
|
-
devgen_cli-0.2.
|
|
43
|
-
devgen_cli-0.2.
|
|
44
|
-
devgen_cli-0.2.
|
|
39
|
+
devgen_cli-0.2.3.dist-info/licenses/LICENSE,sha256=-JHhLXXB2RRUeojKiRRTDHyJ1QiOCtrDfwbahUOb6Yc,35150
|
|
40
|
+
devgen_cli-0.2.3.dist-info/METADATA,sha256=BmEV-sUK8-s3V4K_Gx2mSirHbNRsT6Iu-MZiqfps0jE,6020
|
|
41
|
+
devgen_cli-0.2.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
42
|
+
devgen_cli-0.2.3.dist-info/entry_points.txt,sha256=NdqXSz3M3_0x0I3tFrXEF7r0mwCDmMfUNZbh2HDZSCg,47
|
|
43
|
+
devgen_cli-0.2.3.dist-info/top_level.txt,sha256=u-4SzOUkP7II9PqLZ4PCpIAsxv4tuxuJ4gtdApYG4Bw,7
|
|
44
|
+
devgen_cli-0.2.3.dist-info/RECORD,,
|
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: devgen-cli
|
|
3
|
-
Version: 0.2.1
|
|
4
|
-
Summary: A collection of developer tools
|
|
5
|
-
Home-page: https://github.com/S4NKALP/devgen
|
|
6
|
-
Author: Sankalp Tharu
|
|
7
|
-
Author-email: Sankalp Tharu <sankalptharu50028@gmail.com>
|
|
8
|
-
License: GPL-3.0-or-later
|
|
9
|
-
Project-URL: Homepage, https://github.com/S4NKALP/devgen
|
|
10
|
-
Keywords: devgen,cli,git,changelog,gitignore,license,commit-generator,commit
|
|
11
|
-
Classifier: Development Status :: 3 - Alpha
|
|
12
|
-
Classifier: Intended Audience :: Developers
|
|
13
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
14
|
-
Classifier: Operating System :: OS Independent
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
-
Requires-Python: >=3.10
|
|
21
|
-
Description-Content-Type: text/markdown
|
|
22
|
-
License-File: LICENSE
|
|
23
|
-
Requires-Dist: anthropic>=0.75.0
|
|
24
|
-
Requires-Dist: google-generativeai>=0.8.5
|
|
25
|
-
Requires-Dist: jinja2>=3.1.6
|
|
26
|
-
Requires-Dist: openai>=2.11.0
|
|
27
|
-
Requires-Dist: pyyaml>=6.0.3
|
|
28
|
-
Requires-Dist: questionary>=2.1.1
|
|
29
|
-
Requires-Dist: requests>=2.32.5
|
|
30
|
-
Requires-Dist: rich>=14.2.0
|
|
31
|
-
Requires-Dist: toml>=0.10.2
|
|
32
|
-
Requires-Dist: typer>=0.20.0
|
|
33
|
-
Dynamic: author
|
|
34
|
-
Dynamic: home-page
|
|
35
|
-
Dynamic: license-file
|
|
36
|
-
Dynamic: requires-python
|
|
37
|
-
|
|
38
|
-
# DevGen
|
|
39
|
-
|
|
40
|
-
<div align="center">
|
|
41
|
-
|
|
42
|
-
<img src="https://img.shields.io/pypi/v/devgen?color=blue&label=PyPI&logo=pypi&logoColor=white" alt="PyPI">
|
|
43
|
-
<img src="https://img.shields.io/badge/Python-3.10%2B-3776AB?logo=python&logoColor=white" alt="Python">
|
|
44
|
-
<a href="https://github.com/S4NKALP/devgen/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-GPL--3.0--or--later-blue.svg" alt="License"></a>
|
|
45
|
-
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
**DevGen** is an AI-powered developer toolkit that automates common Git and project management tasks. Generate semantic commit messages, changelogs, release notes, `.gitignore` files, and licenses—all from a single unified CLI.
|
|
49
|
-
|
|
50
|
-
## ✨ Features
|
|
51
|
-
|
|
52
|
-
- 🚀 **AI-Powered Commit Messages** - Automatically generate semantic commit messages from your staged changes using AI
|
|
53
|
-
- 📝 **Changelog Generation** - Create changelogs from git history using conventional commits
|
|
54
|
-
- 🚀 **Release Notes** - Generate clean, emoji-enhanced release notes for your releases
|
|
55
|
-
- 🙈 **Gitignore Templates** - Generate `.gitignore` files from GitHub's official templates
|
|
56
|
-
- 📄 **License Generation** - Quickly generate open source licenses with interactive setup
|
|
57
|
-
- ⚙️ **Multi-Provider AI Support** - Works with Gemini, OpenAI, Anthropic, HuggingFace, and OpenRouter
|
|
58
|
-
|
|
59
|
-
## 📦 Installation
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
# Stable release from PyPI
|
|
63
|
-
pip install devgen-cli
|
|
64
|
-
|
|
65
|
-
# Using pipx (recommended for isolated CLI)
|
|
66
|
-
pipx install devgen-cli
|
|
67
|
-
|
|
68
|
-
# Using uv (fast Python package manager)
|
|
69
|
-
uv tool install devgen-cli
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## 🚀 Quick Start
|
|
73
|
-
|
|
74
|
-
### 1. Initial Setup
|
|
75
|
-
|
|
76
|
-
Configure your AI provider and API key:
|
|
77
|
-
|
|
78
|
-
```bash
|
|
79
|
-
devgen setup config
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
This will create a configuration file at `~/.devgen.yaml` with your preferred AI provider, model, and API key.
|
|
83
|
-
|
|
84
|
-
### 2. Generate Commit Messages
|
|
85
|
-
|
|
86
|
-
Stage your changes and let DevGen generate semantic commit messages:
|
|
87
|
-
|
|
88
|
-
```bash
|
|
89
|
-
# Dry run to preview commit messages
|
|
90
|
-
devgen commit run --dry-run
|
|
91
|
-
|
|
92
|
-
# Actually commit with AI-generated messages
|
|
93
|
-
devgen commit run
|
|
94
|
-
|
|
95
|
-
# Commit and automatically push
|
|
96
|
-
devgen commit run --push
|
|
97
|
-
|
|
98
|
-
# Force regeneration of commit messages
|
|
99
|
-
devgen commit run --force-rebuild
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
**How it works:**
|
|
103
|
-
|
|
104
|
-
- DevGen detects all staged and unstaged changes
|
|
105
|
-
- Groups files by directory
|
|
106
|
-
- Generates semantic commit messages for each group using AI
|
|
107
|
-
- Follows [Conventional Commits](https://www.conventionalcommits.org/) format
|
|
108
|
-
|
|
109
|
-
**Additional commit commands:**
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
# View cached commit messages
|
|
113
|
-
devgen commit list-cached
|
|
114
|
-
|
|
115
|
-
# Clear the commit cache
|
|
116
|
-
devgen commit clear-cache
|
|
117
|
-
|
|
118
|
-
# Check what files are staged
|
|
119
|
-
devgen commit validate
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### 3. Generate Changelogs
|
|
123
|
-
|
|
124
|
-
Create changelogs from your git history:
|
|
125
|
-
|
|
126
|
-
```bash
|
|
127
|
-
# Generate changelog from last tag to HEAD
|
|
128
|
-
devgen changelog generate
|
|
129
|
-
|
|
130
|
-
# Generate from a specific reference
|
|
131
|
-
devgen changelog generate --from v1.0.0
|
|
132
|
-
|
|
133
|
-
# Output to a custom file
|
|
134
|
-
devgen changelog generate --output CHANGES.md
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
The changelog follows Semantic Release conventions, categorizing commits into:
|
|
138
|
-
|
|
139
|
-
- **BREAKING CHANGES**
|
|
140
|
-
- **Features**
|
|
141
|
-
- **Bug Fixes**
|
|
142
|
-
- **Documentation**
|
|
143
|
-
- **Other Changes**
|
|
144
|
-
|
|
145
|
-
### 4. Generate Release Notes
|
|
146
|
-
|
|
147
|
-
Create release notes for your releases:
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
# Generate release notes
|
|
151
|
-
devgen release notes --version 1.4.0
|
|
152
|
-
|
|
153
|
-
# Custom output file
|
|
154
|
-
devgen release notes --version 1.4.0 --output RELEASE.md
|
|
155
|
-
|
|
156
|
-
# From a specific reference
|
|
157
|
-
devgen release notes --version 1.4.0 --from v1.3.0
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### 5. Generate .gitignore Files
|
|
161
|
-
|
|
162
|
-
Create `.gitignore` files from GitHub templates:
|
|
163
|
-
|
|
164
|
-
```bash
|
|
165
|
-
# Interactive mode (search and select templates)
|
|
166
|
-
devgen gitignore generate
|
|
167
|
-
|
|
168
|
-
# Specify templates directly
|
|
169
|
-
devgen gitignore generate Python Node Docker
|
|
170
|
-
|
|
171
|
-
# List available templates
|
|
172
|
-
devgen gitignore list
|
|
173
|
-
|
|
174
|
-
# Use cached templates (offline mode)
|
|
175
|
-
devgen gitignore generate --offline Python
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
**Options:**
|
|
179
|
-
|
|
180
|
-
- `--append` / `--overwrite` - Append to or overwrite existing `.gitignore`
|
|
181
|
-
- `--output` - Specify output file path (default: `.gitignore`)
|
|
182
|
-
- `--offline` - Use only cached templates
|
|
183
|
-
|
|
184
|
-
### 6. Generate Licenses
|
|
185
|
-
|
|
186
|
-
Generate open source licenses interactively:
|
|
187
|
-
|
|
188
|
-
```bash
|
|
189
|
-
devgen license generate
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
This will:
|
|
193
|
-
|
|
194
|
-
1. Show available licenses (MIT, Apache-2.0, GPL-3.0, etc.)
|
|
195
|
-
2. Prompt for author name
|
|
196
|
-
3. Prompt for year (defaults to current year)
|
|
197
|
-
4. Generate the license file
|
|
198
|
-
|
|
199
|
-
**Available licenses:**
|
|
200
|
-
|
|
201
|
-
- MIT
|
|
202
|
-
- Apache-2.0
|
|
203
|
-
- GPL-2.0, GPL-3.0
|
|
204
|
-
- LGPL-2.1
|
|
205
|
-
- AGPL-3.0
|
|
206
|
-
- BSD-2-Clause, BSD-3-Clause
|
|
207
|
-
- MPL-2.0
|
|
208
|
-
- EPL-2.0
|
|
209
|
-
- BSL-1.0
|
|
210
|
-
- CC0-1.0
|
|
211
|
-
- Unlicense
|
|
212
|
-
|
|
213
|
-
## ⚙️ Configuration
|
|
214
|
-
|
|
215
|
-
Configuration is stored in `~/.devgen.yaml`. You can edit it manually or use the interactive setup:
|
|
216
|
-
|
|
217
|
-
```bash
|
|
218
|
-
devgen setup config
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
**Configuration options:**
|
|
222
|
-
|
|
223
|
-
- `provider` - AI provider: `gemini`, `openai`, `anthropic`, `huggingface`, or `openrouter`
|
|
224
|
-
- `model` - Model name (e.g., `gemini-2.5-flash`, `gpt-4`, `claude-3-opus`)
|
|
225
|
-
- `api_key` - Your API key
|
|
226
|
-
- `emoji` - Enable/disable emojis in commit messages (default: `true`)
|
|
227
|
-
|
|
228
|
-
## 📋 Command Reference
|
|
229
|
-
|
|
230
|
-
### Commit Commands
|
|
231
|
-
|
|
232
|
-
```bash
|
|
233
|
-
devgen commit run [--dry-run] [--push] [--debug] [--force-rebuild]
|
|
234
|
-
devgen commit validate
|
|
235
|
-
devgen commit list-cached
|
|
236
|
-
devgen commit clear-cache
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
### Changelog Commands
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
devgen changelog generate [--output FILE] [--from REF]
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
### Release Commands
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
devgen release notes [--version VERSION] [--output FILE] [--from REF]
|
|
249
|
-
```
|
|
250
|
-
|
|
251
|
-
### Gitignore Commands
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
devgen gitignore generate [TEMPLATES...] [--output FILE] [--append/--overwrite] [--offline]
|
|
255
|
-
devgen gitignore list [--cached]
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
### License Commands
|
|
259
|
-
|
|
260
|
-
```bash
|
|
261
|
-
devgen license generate [--output FILE]
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
### Setup Commands
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
devgen setup config
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
## 🎯 Use Cases
|
|
271
|
-
|
|
272
|
-
- **Automated Commit Workflow**: Let AI analyze your changes and generate meaningful commit messages
|
|
273
|
-
- **Release Preparation**: Automatically generate changelogs and release notes from git history
|
|
274
|
-
- **Project Setup**: Quickly add `.gitignore` and license files to new projects
|
|
275
|
-
- **CI/CD Integration**: Use in scripts to automate documentation generation
|
|
276
|
-
|
|
277
|
-
## 🔧 Requirements
|
|
278
|
-
|
|
279
|
-
- Python 3.10 or higher
|
|
280
|
-
- Git repository (for commit/changelog/release features)
|
|
281
|
-
- API key for your chosen AI provider
|
|
282
|
-
|
|
283
|
-
## 📝 License
|
|
284
|
-
|
|
285
|
-
This project is licensed under the GPL-3.0-or-later License - see the [LICENSE](LICENSE) file for details.
|
|
286
|
-
|
|
287
|
-
## 🤝 Contributing
|
|
288
|
-
|
|
289
|
-
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
290
|
-
|
|
291
|
-
## 📚 Links
|
|
292
|
-
|
|
293
|
-
- **Homepage**: [https://github.com/S4NKALP/devgen](https://github.com/S4NKALP/devgen)
|
|
294
|
-
- **PyPI**: [https://pypi.org/project/devgen](https://pypi.org/project/devgen)
|
|
295
|
-
|
|
296
|
-
## 🙏 Acknowledgments
|
|
297
|
-
|
|
298
|
-
- Uses GitHub's official [gitignore templates](https://github.com/github/gitignore)
|
|
299
|
-
- Follows [Conventional Commits](https://www.conventionalcommits.org/) specification
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|