git-auto-pro 1.0.0__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.
- git_auto_pro/__init__.py +5 -0
- git_auto_pro/backup.py +87 -0
- git_auto_pro/cli.py +474 -0
- git_auto_pro/config.py +100 -0
- git_auto_pro/git_commands.py +426 -0
- git_auto_pro/github.py +318 -0
- git_auto_pro/gitignore_manager.py +400 -0
- git_auto_pro/scaffolding/__init__.py +1 -0
- git_auto_pro/scaffolding/github_templates.py +635 -0
- git_auto_pro/scaffolding/gitignore.py +149 -0
- git_auto_pro/scaffolding/hooks.py +331 -0
- git_auto_pro/scaffolding/license.py +109 -0
- git_auto_pro/scaffolding/project.py +83 -0
- git_auto_pro/scaffolding/readme.py +109 -0
- git_auto_pro/scaffolding/templates.py +336 -0
- git_auto_pro/scaffolding/workflows.py +236 -0
- git_auto_pro-1.0.0.dist-info/METADATA +477 -0
- git_auto_pro-1.0.0.dist-info/RECORD +22 -0
- git_auto_pro-1.0.0.dist-info/WHEEL +5 -0
- git_auto_pro-1.0.0.dist-info/entry_points.txt +2 -0
- git_auto_pro-1.0.0.dist-info/licenses/LICENSE +0 -0
- git_auto_pro-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""README.md generator."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
import questionary
|
|
7
|
+
|
|
8
|
+
console = Console()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
README_TEMPLATE = """# {title}
|
|
12
|
+
|
|
13
|
+
{description}
|
|
14
|
+
|
|
15
|
+
## Features
|
|
16
|
+
|
|
17
|
+
{features}
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
{installation}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
{usage}
|
|
28
|
+
|
|
29
|
+
## Screenshots
|
|
30
|
+
|
|
31
|
+
{screenshots}
|
|
32
|
+
|
|
33
|
+
## Contributing
|
|
34
|
+
|
|
35
|
+
{contributing}
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
This project is licensed under the {license} License - see the [LICENSE](LICENSE) file for details.
|
|
40
|
+
|
|
41
|
+
## Contact
|
|
42
|
+
|
|
43
|
+
{contact}
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def generate_readme(interactive: bool = True, output: str = "README.md") -> None:
|
|
48
|
+
"""Generate professional README.md."""
|
|
49
|
+
console.print("[bold cyan]📝 Generating README.md[/bold cyan]\n")
|
|
50
|
+
|
|
51
|
+
if interactive:
|
|
52
|
+
title = questionary.text("Project title:", default="My Awesome Project").ask()
|
|
53
|
+
description = questionary.text(
|
|
54
|
+
"Project description:",
|
|
55
|
+
default="A brief description of what this project does"
|
|
56
|
+
).ask()
|
|
57
|
+
|
|
58
|
+
features = questionary.text(
|
|
59
|
+
"Key features (comma-separated):",
|
|
60
|
+
default="Feature 1, Feature 2, Feature 3"
|
|
61
|
+
).ask()
|
|
62
|
+
features_list = "\n".join(f"- {f.strip()}" for f in features.split(","))
|
|
63
|
+
|
|
64
|
+
installation = questionary.text(
|
|
65
|
+
"Installation command:",
|
|
66
|
+
default="pip install project-name"
|
|
67
|
+
).ask()
|
|
68
|
+
|
|
69
|
+
usage = questionary.text(
|
|
70
|
+
"Usage example:",
|
|
71
|
+
default="from project import main\nmain()"
|
|
72
|
+
).ask()
|
|
73
|
+
|
|
74
|
+
license_type = questionary.select(
|
|
75
|
+
"License:",
|
|
76
|
+
choices=["MIT", "Apache-2.0", "GPL-3.0", "BSD-3-Clause", "Other"]
|
|
77
|
+
).ask()
|
|
78
|
+
|
|
79
|
+
contact = questionary.text(
|
|
80
|
+
"Contact information:",
|
|
81
|
+
default="Your Name - [@yourhandle](https://twitter.com/yourhandle)"
|
|
82
|
+
).ask()
|
|
83
|
+
else:
|
|
84
|
+
# Default values for non-interactive mode
|
|
85
|
+
title = Path.cwd().name.replace("-", " ").replace("_", " ").title()
|
|
86
|
+
description = "A brief description of this project"
|
|
87
|
+
features_list = "- Feature 1\n- Feature 2\n- Feature 3"
|
|
88
|
+
installation = "pip install package-name"
|
|
89
|
+
usage = "```python\nimport package\n```"
|
|
90
|
+
license_type = "MIT"
|
|
91
|
+
contact = "Your Name - your.email@example.com"
|
|
92
|
+
|
|
93
|
+
readme_content = README_TEMPLATE.format(
|
|
94
|
+
title=title if interactive else title,
|
|
95
|
+
description=description,
|
|
96
|
+
features=features_list,
|
|
97
|
+
installation=installation,
|
|
98
|
+
usage=usage if interactive else usage,
|
|
99
|
+
screenshots="Add screenshots here",
|
|
100
|
+
contributing="Contributions are welcome! Please feel free to submit a Pull Request.",
|
|
101
|
+
license=license_type,
|
|
102
|
+
contact=contact,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
with open(output, "w") as f:
|
|
106
|
+
f.write(readme_content)
|
|
107
|
+
|
|
108
|
+
console.print(f"[green]✓ README.md generated: {output}[/green]")
|
|
109
|
+
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
"""Project template generator."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
console = Console()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def generate_template(type: str, output: Optional[str] = None) -> None:
|
|
11
|
+
"""Generate project template structure."""
|
|
12
|
+
console.print(f"[bold cyan]📋 Generating {type} template[/bold cyan]\n")
|
|
13
|
+
|
|
14
|
+
base_path = Path(output) if output else Path(".")
|
|
15
|
+
|
|
16
|
+
templates = {
|
|
17
|
+
"python": generate_python_template,
|
|
18
|
+
"node": generate_node_template,
|
|
19
|
+
"cpp": generate_cpp_template,
|
|
20
|
+
"web": generate_web_template,
|
|
21
|
+
"rust": generate_rust_template,
|
|
22
|
+
"go": generate_go_template,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
generator = templates.get(type)
|
|
26
|
+
if generator:
|
|
27
|
+
generator(base_path)
|
|
28
|
+
console.print(f"[green]✓ {type.title()} template generated[/green]")
|
|
29
|
+
else:
|
|
30
|
+
console.print(f"[red]✗ Unknown template type: {type}[/red]")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def generate_python_template(base_path: Path) -> None:
|
|
34
|
+
"""Generate Python project template."""
|
|
35
|
+
# Create directory structure
|
|
36
|
+
(base_path / "src").mkdir(exist_ok=True)
|
|
37
|
+
(base_path / "tests").mkdir(exist_ok=True)
|
|
38
|
+
(base_path / "docs").mkdir(exist_ok=True)
|
|
39
|
+
|
|
40
|
+
# __init__.py
|
|
41
|
+
(base_path / "src" / "__init__.py").write_text('"""Package initialization."""\n\n__version__ = "0.1.0"\n')
|
|
42
|
+
|
|
43
|
+
# main.py
|
|
44
|
+
(base_path / "src" / "main.py").write_text('''"""Main module."""
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def main():
|
|
48
|
+
"""Main entry point."""
|
|
49
|
+
print("Hello, World!")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
main()
|
|
54
|
+
''')
|
|
55
|
+
|
|
56
|
+
# tests
|
|
57
|
+
(base_path / "tests" / "__init__.py").write_text("")
|
|
58
|
+
(base_path / "tests" / "test_main.py").write_text('''"""Tests for main module."""
|
|
59
|
+
|
|
60
|
+
import pytest
|
|
61
|
+
from src.main import main
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_main():
|
|
65
|
+
"""Test main function."""
|
|
66
|
+
main() # Should not raise
|
|
67
|
+
''')
|
|
68
|
+
|
|
69
|
+
# requirements.txt
|
|
70
|
+
(base_path / "requirements.txt").write_text("# Add your dependencies here\n")
|
|
71
|
+
|
|
72
|
+
# requirements-dev.txt
|
|
73
|
+
(base_path / "requirements-dev.txt").write_text("""pytest>=7.4.0
|
|
74
|
+
pytest-cov>=4.1.0
|
|
75
|
+
black>=23.0.0
|
|
76
|
+
ruff>=0.1.0
|
|
77
|
+
mypy>=1.5.0
|
|
78
|
+
""")
|
|
79
|
+
|
|
80
|
+
# setup.py
|
|
81
|
+
(base_path / "setup.py").write_text('''"""Setup script."""
|
|
82
|
+
|
|
83
|
+
from setuptools import setup, find_packages
|
|
84
|
+
|
|
85
|
+
setup(
|
|
86
|
+
name="project-name",
|
|
87
|
+
version="0.1.0",
|
|
88
|
+
packages=find_packages(),
|
|
89
|
+
install_requires=[],
|
|
90
|
+
python_requires=">=3.8",
|
|
91
|
+
)
|
|
92
|
+
''')
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def generate_node_template(base_path: Path) -> None:
|
|
96
|
+
"""Generate Node.js project template."""
|
|
97
|
+
# Create directory structure
|
|
98
|
+
(base_path / "src").mkdir(exist_ok=True)
|
|
99
|
+
(base_path / "tests").mkdir(exist_ok=True)
|
|
100
|
+
(base_path / "public").mkdir(exist_ok=True)
|
|
101
|
+
|
|
102
|
+
# package.json
|
|
103
|
+
(base_path / "package.json").write_text('''{
|
|
104
|
+
"name": "project-name",
|
|
105
|
+
"version": "1.0.0",
|
|
106
|
+
"description": "Project description",
|
|
107
|
+
"main": "src/index.js",
|
|
108
|
+
"scripts": {
|
|
109
|
+
"start": "node src/index.js",
|
|
110
|
+
"test": "jest",
|
|
111
|
+
"dev": "nodemon src/index.js"
|
|
112
|
+
},
|
|
113
|
+
"keywords": [],
|
|
114
|
+
"author": "",
|
|
115
|
+
"license": "MIT",
|
|
116
|
+
"devDependencies": {
|
|
117
|
+
"jest": "^29.0.0",
|
|
118
|
+
"nodemon": "^3.0.0"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
''')
|
|
122
|
+
|
|
123
|
+
# index.js
|
|
124
|
+
(base_path / "src" / "index.js").write_text('''/**
|
|
125
|
+
* Main entry point
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
function main() {
|
|
129
|
+
console.log('Hello, World!');
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
main();
|
|
133
|
+
|
|
134
|
+
module.exports = { main };
|
|
135
|
+
''')
|
|
136
|
+
|
|
137
|
+
# test
|
|
138
|
+
(base_path / "tests" / "index.test.js").write_text('''const { main } = require('../src/index');
|
|
139
|
+
|
|
140
|
+
describe('Main', () => {
|
|
141
|
+
test('should run without errors', () => {
|
|
142
|
+
expect(() => main()).not.toThrow();
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
''')
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def generate_cpp_template(base_path: Path) -> None:
|
|
149
|
+
"""Generate C++ project template."""
|
|
150
|
+
# Create directory structure
|
|
151
|
+
(base_path / "src").mkdir(exist_ok=True)
|
|
152
|
+
(base_path / "include").mkdir(exist_ok=True)
|
|
153
|
+
(base_path / "tests").mkdir(exist_ok=True)
|
|
154
|
+
(base_path / "build").mkdir(exist_ok=True)
|
|
155
|
+
|
|
156
|
+
# main.cpp
|
|
157
|
+
(base_path / "src" / "main.cpp").write_text('''#include <iostream>
|
|
158
|
+
#include "main.h"
|
|
159
|
+
|
|
160
|
+
int main() {
|
|
161
|
+
std::cout << "Hello, World!" << std::endl;
|
|
162
|
+
return 0;
|
|
163
|
+
}
|
|
164
|
+
''')
|
|
165
|
+
|
|
166
|
+
# header
|
|
167
|
+
(base_path / "include" / "main.h").write_text('''#ifndef MAIN_H
|
|
168
|
+
#define MAIN_H
|
|
169
|
+
|
|
170
|
+
// Function declarations
|
|
171
|
+
|
|
172
|
+
#endif // MAIN_H
|
|
173
|
+
''')
|
|
174
|
+
|
|
175
|
+
# CMakeLists.txt
|
|
176
|
+
(base_path / "CMakeLists.txt").write_text('''cmake_minimum_required(VERSION 3.10)
|
|
177
|
+
project(ProjectName)
|
|
178
|
+
|
|
179
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
180
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
181
|
+
|
|
182
|
+
include_directories(include)
|
|
183
|
+
|
|
184
|
+
add_executable(${PROJECT_NAME} src/main.cpp)
|
|
185
|
+
|
|
186
|
+
# Tests
|
|
187
|
+
enable_testing()
|
|
188
|
+
add_subdirectory(tests)
|
|
189
|
+
''')
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def generate_web_template(base_path: Path) -> None:
|
|
193
|
+
"""Generate basic web project template."""
|
|
194
|
+
# Create directory structure
|
|
195
|
+
(base_path / "css").mkdir(exist_ok=True)
|
|
196
|
+
(base_path / "js").mkdir(exist_ok=True)
|
|
197
|
+
(base_path / "img").mkdir(exist_ok=True)
|
|
198
|
+
|
|
199
|
+
# index.html
|
|
200
|
+
(base_path / "index.html").write_text('''<!DOCTYPE html>
|
|
201
|
+
<html lang="en">
|
|
202
|
+
<head>
|
|
203
|
+
<meta charset="UTF-8">
|
|
204
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
205
|
+
<title>Project Name</title>
|
|
206
|
+
<link rel="stylesheet" href="css/style.css">
|
|
207
|
+
</head>
|
|
208
|
+
<body>
|
|
209
|
+
<header>
|
|
210
|
+
<h1>Welcome to My Project</h1>
|
|
211
|
+
</header>
|
|
212
|
+
|
|
213
|
+
<main>
|
|
214
|
+
<section>
|
|
215
|
+
<h2>About</h2>
|
|
216
|
+
<p>This is a sample web project.</p>
|
|
217
|
+
</section>
|
|
218
|
+
</main>
|
|
219
|
+
|
|
220
|
+
<footer>
|
|
221
|
+
<p>© 2024 Your Name</p>
|
|
222
|
+
</footer>
|
|
223
|
+
|
|
224
|
+
<script src="js/main.js"></script>
|
|
225
|
+
</body>
|
|
226
|
+
</html>
|
|
227
|
+
''')
|
|
228
|
+
|
|
229
|
+
# style.css
|
|
230
|
+
(base_path / "css" / "style.css").write_text('''* {
|
|
231
|
+
margin: 0;
|
|
232
|
+
padding: 0;
|
|
233
|
+
box-sizing: border-box;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
body {
|
|
237
|
+
font-family: Arial, sans-serif;
|
|
238
|
+
line-height: 1.6;
|
|
239
|
+
color: #333;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
header {
|
|
243
|
+
background: #333;
|
|
244
|
+
color: #fff;
|
|
245
|
+
text-align: center;
|
|
246
|
+
padding: 1rem;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
main {
|
|
250
|
+
max-width: 1200px;
|
|
251
|
+
margin: 2rem auto;
|
|
252
|
+
padding: 0 2rem;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
footer {
|
|
256
|
+
background: #333;
|
|
257
|
+
color: #fff;
|
|
258
|
+
text-align: center;
|
|
259
|
+
padding: 1rem;
|
|
260
|
+
margin-top: 2rem;
|
|
261
|
+
}
|
|
262
|
+
''')
|
|
263
|
+
|
|
264
|
+
# main.js
|
|
265
|
+
(base_path / "js" / "main.js").write_text('''// Main JavaScript file
|
|
266
|
+
|
|
267
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
268
|
+
console.log('Page loaded!');
|
|
269
|
+
});
|
|
270
|
+
''')
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def generate_rust_template(base_path: Path) -> None:
|
|
274
|
+
"""Generate Rust project template."""
|
|
275
|
+
# Create directory structure
|
|
276
|
+
(base_path / "src").mkdir(exist_ok=True)
|
|
277
|
+
(base_path / "tests").mkdir(exist_ok=True)
|
|
278
|
+
|
|
279
|
+
# Cargo.toml
|
|
280
|
+
(base_path / "Cargo.toml").write_text('''[package]
|
|
281
|
+
name = "project-name"
|
|
282
|
+
version = "0.1.0"
|
|
283
|
+
edition = "2021"
|
|
284
|
+
|
|
285
|
+
[dependencies]
|
|
286
|
+
|
|
287
|
+
[dev-dependencies]
|
|
288
|
+
''')
|
|
289
|
+
|
|
290
|
+
# main.rs
|
|
291
|
+
(base_path / "src" / "main.rs").write_text('''fn main() {
|
|
292
|
+
println!("Hello, world!");
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
#[cfg(test)]
|
|
296
|
+
mod tests {
|
|
297
|
+
#[test]
|
|
298
|
+
fn it_works() {
|
|
299
|
+
assert_eq!(2 + 2, 4);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
''')
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
def generate_go_template(base_path: Path) -> None:
|
|
306
|
+
"""Generate Go project template."""
|
|
307
|
+
# Create directory structure
|
|
308
|
+
(base_path / "cmd").mkdir(exist_ok=True)
|
|
309
|
+
(base_path / "pkg").mkdir(exist_ok=True)
|
|
310
|
+
(base_path / "internal").mkdir(exist_ok=True)
|
|
311
|
+
|
|
312
|
+
# go.mod
|
|
313
|
+
(base_path / "go.mod").write_text('''module github.com/username/project-name
|
|
314
|
+
|
|
315
|
+
go 1.21
|
|
316
|
+
''')
|
|
317
|
+
|
|
318
|
+
# main.go
|
|
319
|
+
(base_path / "cmd" / "main.go").write_text('''package main
|
|
320
|
+
|
|
321
|
+
import "fmt"
|
|
322
|
+
|
|
323
|
+
func main() {
|
|
324
|
+
fmt.Println("Hello, World!")
|
|
325
|
+
}
|
|
326
|
+
''')
|
|
327
|
+
|
|
328
|
+
# main_test.go
|
|
329
|
+
(base_path / "cmd" / "main_test.go").write_text('''package main
|
|
330
|
+
|
|
331
|
+
import "testing"
|
|
332
|
+
|
|
333
|
+
func TestMain(t *testing.T) {
|
|
334
|
+
// Add tests here
|
|
335
|
+
}
|
|
336
|
+
''')
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"""CI/CD workflow generator."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import Optional
|
|
5
|
+
from rich.console import Console
|
|
6
|
+
|
|
7
|
+
console = Console()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def generate_workflow(type: str, platform: str = "github") -> None:
|
|
11
|
+
"""Generate CI/CD workflow files."""
|
|
12
|
+
console.print(f"[bold cyan]⚙️ Generating {type} workflow for {platform}[/bold cyan]\n")
|
|
13
|
+
|
|
14
|
+
if platform == "github":
|
|
15
|
+
generate_github_workflow(type)
|
|
16
|
+
elif platform == "gitlab":
|
|
17
|
+
generate_gitlab_workflow(type)
|
|
18
|
+
else:
|
|
19
|
+
console.print(f"[red]✗ Unsupported platform: {platform}[/red]")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def generate_github_workflow(type: str) -> None:
|
|
23
|
+
"""Generate GitHub Actions workflow."""
|
|
24
|
+
workflows_dir = Path(".github/workflows")
|
|
25
|
+
workflows_dir.mkdir(parents=True, exist_ok=True)
|
|
26
|
+
|
|
27
|
+
workflows = {
|
|
28
|
+
"ci": GITHUB_CI_WORKFLOW,
|
|
29
|
+
"test": GITHUB_TEST_WORKFLOW,
|
|
30
|
+
"cd": GITHUB_CD_WORKFLOW,
|
|
31
|
+
"release": GITHUB_RELEASE_WORKFLOW,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
content = workflows.get(type)
|
|
35
|
+
if content:
|
|
36
|
+
output_file = workflows_dir / f"{type}.yml"
|
|
37
|
+
output_file.write_text(content)
|
|
38
|
+
console.print(f"[green]✓ Workflow generated: {output_file}[/green]")
|
|
39
|
+
else:
|
|
40
|
+
console.print(f"[red]✗ Unknown workflow type: {type}[/red]")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
GITHUB_CI_WORKFLOW = """name: CI
|
|
44
|
+
|
|
45
|
+
on:
|
|
46
|
+
push:
|
|
47
|
+
branches: [ main, develop ]
|
|
48
|
+
pull_request:
|
|
49
|
+
branches: [ main, develop ]
|
|
50
|
+
|
|
51
|
+
jobs:
|
|
52
|
+
build:
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
|
|
55
|
+
strategy:
|
|
56
|
+
matrix:
|
|
57
|
+
python-version: [3.8, 3.9, '3.10', 3.11]
|
|
58
|
+
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@v3
|
|
61
|
+
|
|
62
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
63
|
+
uses: actions/setup-python@v4
|
|
64
|
+
with:
|
|
65
|
+
python-version: ${{ matrix.python-version }}
|
|
66
|
+
|
|
67
|
+
- name: Install dependencies
|
|
68
|
+
run: |
|
|
69
|
+
python -m pip install --upgrade pip
|
|
70
|
+
pip install -r requirements.txt
|
|
71
|
+
pip install -r requirements-dev.txt
|
|
72
|
+
|
|
73
|
+
- name: Lint with ruff
|
|
74
|
+
run: |
|
|
75
|
+
ruff check .
|
|
76
|
+
|
|
77
|
+
- name: Format check with black
|
|
78
|
+
run: |
|
|
79
|
+
black --check .
|
|
80
|
+
|
|
81
|
+
- name: Type check with mypy
|
|
82
|
+
run: |
|
|
83
|
+
mypy .
|
|
84
|
+
|
|
85
|
+
- name: Test with pytest
|
|
86
|
+
run: |
|
|
87
|
+
pytest --cov=. --cov-report=xml
|
|
88
|
+
|
|
89
|
+
- name: Upload coverage
|
|
90
|
+
uses: codecov/codecov-action@v3
|
|
91
|
+
with:
|
|
92
|
+
file: ./coverage.xml
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
GITHUB_TEST_WORKFLOW = """name: Tests
|
|
96
|
+
|
|
97
|
+
on:
|
|
98
|
+
push:
|
|
99
|
+
branches: [ main, develop ]
|
|
100
|
+
pull_request:
|
|
101
|
+
branches: [ main, develop ]
|
|
102
|
+
|
|
103
|
+
jobs:
|
|
104
|
+
test:
|
|
105
|
+
runs-on: ${{ matrix.os }}
|
|
106
|
+
|
|
107
|
+
strategy:
|
|
108
|
+
matrix:
|
|
109
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
110
|
+
python-version: [3.8, 3.9, '3.10', 3.11]
|
|
111
|
+
|
|
112
|
+
steps:
|
|
113
|
+
- uses: actions/checkout@v3
|
|
114
|
+
|
|
115
|
+
- name: Set up Python
|
|
116
|
+
uses: actions/setup-python@v4
|
|
117
|
+
with:
|
|
118
|
+
python-version: ${{ matrix.python-version }}
|
|
119
|
+
|
|
120
|
+
- name: Install dependencies
|
|
121
|
+
run: |
|
|
122
|
+
python -m pip install --upgrade pip
|
|
123
|
+
pip install pytest pytest-cov
|
|
124
|
+
|
|
125
|
+
- name: Run tests
|
|
126
|
+
run: |
|
|
127
|
+
pytest -v
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
GITHUB_CD_WORKFLOW = """name: CD
|
|
131
|
+
|
|
132
|
+
on:
|
|
133
|
+
release:
|
|
134
|
+
types: [published]
|
|
135
|
+
|
|
136
|
+
jobs:
|
|
137
|
+
deploy:
|
|
138
|
+
runs-on: ubuntu-latest
|
|
139
|
+
|
|
140
|
+
steps:
|
|
141
|
+
- uses: actions/checkout@v3
|
|
142
|
+
|
|
143
|
+
- name: Set up Python
|
|
144
|
+
uses: actions/setup-python@v4
|
|
145
|
+
with:
|
|
146
|
+
python-version: '3.10'
|
|
147
|
+
|
|
148
|
+
- name: Install dependencies
|
|
149
|
+
run: |
|
|
150
|
+
python -m pip install --upgrade pip
|
|
151
|
+
pip install build twine
|
|
152
|
+
|
|
153
|
+
- name: Build package
|
|
154
|
+
run: python -m build
|
|
155
|
+
|
|
156
|
+
- name: Publish to PyPI
|
|
157
|
+
env:
|
|
158
|
+
TWINE_USERNAME: __token__
|
|
159
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
|
|
160
|
+
run: twine upload dist/*
|
|
161
|
+
"""
|
|
162
|
+
|
|
163
|
+
GITHUB_RELEASE_WORKFLOW = """name: Release
|
|
164
|
+
|
|
165
|
+
on:
|
|
166
|
+
push:
|
|
167
|
+
tags:
|
|
168
|
+
- 'v*'
|
|
169
|
+
|
|
170
|
+
jobs:
|
|
171
|
+
release:
|
|
172
|
+
runs-on: ubuntu-latest
|
|
173
|
+
|
|
174
|
+
steps:
|
|
175
|
+
- uses: actions/checkout@v3
|
|
176
|
+
|
|
177
|
+
- name: Create Release
|
|
178
|
+
uses: actions/create-release@v1
|
|
179
|
+
env:
|
|
180
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
181
|
+
with:
|
|
182
|
+
tag_name: ${{ github.ref }}
|
|
183
|
+
release_name: Release ${{ github.ref }}
|
|
184
|
+
draft: false
|
|
185
|
+
prerelease: false
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def generate_gitlab_workflow(type: str) -> None:
|
|
190
|
+
"""Generate GitLab CI workflow."""
|
|
191
|
+
content = GITLAB_CI_CONFIG
|
|
192
|
+
|
|
193
|
+
Path(".gitlab-ci.yml").write_text(content)
|
|
194
|
+
console.print("[green]✓ GitLab CI config generated: .gitlab-ci.yml[/green]")
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
GITLAB_CI_CONFIG = """stages:
|
|
198
|
+
- test
|
|
199
|
+
- build
|
|
200
|
+
- deploy
|
|
201
|
+
|
|
202
|
+
variables:
|
|
203
|
+
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
|
|
204
|
+
|
|
205
|
+
cache:
|
|
206
|
+
paths:
|
|
207
|
+
- .cache/pip
|
|
208
|
+
|
|
209
|
+
test:
|
|
210
|
+
stage: test
|
|
211
|
+
image: python:3.10
|
|
212
|
+
script:
|
|
213
|
+
- pip install -r requirements.txt
|
|
214
|
+
- pip install pytest pytest-cov
|
|
215
|
+
- pytest --cov=.
|
|
216
|
+
coverage: '/TOTAL.*\\s+(\\d+%)$/'
|
|
217
|
+
|
|
218
|
+
build:
|
|
219
|
+
stage: build
|
|
220
|
+
image: python:3.10
|
|
221
|
+
script:
|
|
222
|
+
- pip install build
|
|
223
|
+
- python -m build
|
|
224
|
+
artifacts:
|
|
225
|
+
paths:
|
|
226
|
+
- dist/
|
|
227
|
+
|
|
228
|
+
deploy:
|
|
229
|
+
stage: deploy
|
|
230
|
+
image: python:3.10
|
|
231
|
+
script:
|
|
232
|
+
- pip install twine
|
|
233
|
+
- twine upload dist/*
|
|
234
|
+
only:
|
|
235
|
+
- tags
|
|
236
|
+
"""
|