devcore-cli 1.0.1__tar.gz → 1.0.4__tar.gz
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.
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/PKG-INFO +1 -1
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/README.md +44 -1
- devcore_cli-1.0.4/devcore.py +265 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/devcore_cli.egg-info/PKG-INFO +1 -1
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/devcore_cli.egg-info/SOURCES.txt +1 -0
- devcore_cli-1.0.4/devcore_cli.egg-info/top_level.txt +2 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/setup.py +4 -2
- devcore_cli-1.0.1/devcore_cli.egg-info/top_level.txt +0 -1
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/__init__.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/command_config.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/command_wp_setup.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/db.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/env_manager.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/github_integration.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/template_engine.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/wp_dropdb.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/core/wp_init.py +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/devcore_cli.egg-info/dependency_links.txt +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/devcore_cli.egg-info/entry_points.txt +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/devcore_cli.egg-info/requires.txt +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/pyproject.toml +0 -0
- {devcore_cli-1.0.1 → devcore_cli-1.0.4}/setup.cfg +0 -0
|
@@ -89,7 +89,7 @@ dev-core-system/
|
|
|
89
89
|
│
|
|
90
90
|
├── .devcore.json
|
|
91
91
|
├── devcore_projects.db
|
|
92
|
-
├── devcore
|
|
92
|
+
├── devcore.py
|
|
93
93
|
├── devcore.cmd
|
|
94
94
|
├── README.md
|
|
95
95
|
└── DOCUMENTATION.md
|
|
@@ -109,6 +109,49 @@ dev-core-system/
|
|
|
109
109
|
|
|
110
110
|
MIT License © 2025 — [DevCore Project Team > Puji Ermanto<pujiermanto@gmail.com>]
|
|
111
111
|
|
|
112
|
+
|
|
113
|
+
#### Notes Error fixed
|
|
114
|
+
```bash
|
|
115
|
+
rm -rf build dist *.egg-info
|
|
116
|
+
pip uninstall devcore-cli -y
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Rebuild & publish
|
|
120
|
+
```bash
|
|
121
|
+
python -m build
|
|
122
|
+
pip install --upgrade build
|
|
123
|
+
twine upload dist/*
|
|
124
|
+
|
|
125
|
+
# 1️⃣ Bersihkan dulu build lama
|
|
126
|
+
rm -rf build dist *.egg-info
|
|
127
|
+
|
|
128
|
+
# 2️⃣ Build ulang package
|
|
129
|
+
python setup.py sdist bdist_wheel
|
|
130
|
+
|
|
131
|
+
# 3️⃣ Install ulang ke environment aktif
|
|
132
|
+
pip install --upgrade --force-reinstall dist/devcore_cli-1.0.3-py3-none-any.whl
|
|
133
|
+
|
|
134
|
+
# 1. Bersihkan build lama
|
|
135
|
+
rm -rf build dist *.egg-info
|
|
136
|
+
|
|
137
|
+
# 2. Build ulang
|
|
138
|
+
python -m build
|
|
139
|
+
|
|
140
|
+
# 3. Upload ke PyPI
|
|
141
|
+
twine upload dist/*
|
|
142
|
+
|
|
143
|
+
# 4. Instal versi terbaru
|
|
144
|
+
pip install --no-cache-dir -U devcore-cli
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
#### Testing
|
|
150
|
+
```bash
|
|
151
|
+
pip install --no-cache-dir -U devcore-cli
|
|
152
|
+
devcore --help
|
|
153
|
+
```
|
|
154
|
+
|
|
112
155
|
💬 Kontribusi
|
|
113
156
|
|
|
114
157
|
Pull Request, Issue, dan Feedback selalu terbuka.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
DevCore CLI with Template Engine (Python)
|
|
4
|
+
|
|
5
|
+
Enhancement: Added support for dynamic template generation using Jinja2.
|
|
6
|
+
|
|
7
|
+
Usage examples:
|
|
8
|
+
python devcore_cli.py new project --type wordpress --client "Evadne Beauty" --stack "wordpress+woo" --init-git
|
|
9
|
+
python devcore_cli.py list
|
|
10
|
+
|
|
11
|
+
This version supports:
|
|
12
|
+
- Jinja2-based templating for files (README.md, .env, docker-compose.yml, etc.)
|
|
13
|
+
- Custom template directory (defaults to ./templates)
|
|
14
|
+
- Auto-create SQLite project record
|
|
15
|
+
- Git init (optional)
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
from core.github_integration import github_login, github_init, github_connect
|
|
19
|
+
from core.wp_init import init_wp_project
|
|
20
|
+
from core.wp_dropdb import drop_wp_database
|
|
21
|
+
from core.command_config import cmd_reset_config
|
|
22
|
+
from core.command_wp_setup import cmd_wp_setup, generate_project_config
|
|
23
|
+
from core.env_manager import rebuild_env_config
|
|
24
|
+
|
|
25
|
+
import argparse
|
|
26
|
+
import argparse
|
|
27
|
+
import os
|
|
28
|
+
import sqlite3
|
|
29
|
+
import subprocess
|
|
30
|
+
import sys
|
|
31
|
+
import shutil
|
|
32
|
+
from datetime import datetime
|
|
33
|
+
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
34
|
+
from core import env_manager
|
|
35
|
+
|
|
36
|
+
DB_PATH = os.path.join(os.getcwd(), "devcore_projects.db")
|
|
37
|
+
TEMPLATE_DIR = os.path.join(os.getcwd(), "templates")
|
|
38
|
+
|
|
39
|
+
def ensure_db():
|
|
40
|
+
conn = sqlite3.connect(DB_PATH)
|
|
41
|
+
cur = conn.cursor()
|
|
42
|
+
cur.execute("""
|
|
43
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
44
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
45
|
+
name TEXT,
|
|
46
|
+
client_name TEXT,
|
|
47
|
+
project_type TEXT,
|
|
48
|
+
stack TEXT,
|
|
49
|
+
path TEXT,
|
|
50
|
+
repo_url TEXT,
|
|
51
|
+
status TEXT,
|
|
52
|
+
created_at TEXT
|
|
53
|
+
)
|
|
54
|
+
""")
|
|
55
|
+
conn.commit()
|
|
56
|
+
cur.execute("SELECT id, name, client_name, project_type, stack, path, repo_url, status, created_at FROM projects ORDER BY id DESC")
|
|
57
|
+
rows = cur.fetchall()
|
|
58
|
+
for r in rows:
|
|
59
|
+
print(f"[{r[0]}] {r[1]} ({r[2]}) — {r[3]} — {r[6]} — {r[7]} — {r[8]}")
|
|
60
|
+
conn.close()
|
|
61
|
+
|
|
62
|
+
def add_project_to_db(name, client_name, project_type, stack, path, repo_url=None, status="created"):
|
|
63
|
+
conn = sqlite3.connect(DB_PATH)
|
|
64
|
+
cur = conn.cursor()
|
|
65
|
+
cur.execute(
|
|
66
|
+
"INSERT INTO projects (name, client_name, project_type, stack, path, repo_url, status, created_at) VALUES (?,?,?,?,?,?,?,?)",
|
|
67
|
+
(name, client_name, project_type, stack, path, repo_url, status, datetime.utcnow().isoformat()),
|
|
68
|
+
)
|
|
69
|
+
conn.commit()
|
|
70
|
+
conn.close()
|
|
71
|
+
|
|
72
|
+
def shutil_which(cmd):
|
|
73
|
+
from shutil import which
|
|
74
|
+
return which(cmd)
|
|
75
|
+
|
|
76
|
+
def init_git_repo(path):
|
|
77
|
+
if not shutil_which("git"):
|
|
78
|
+
print("Git not available, skipping.")
|
|
79
|
+
return None
|
|
80
|
+
try:
|
|
81
|
+
subprocess.check_call(["git", "init"], cwd=path)
|
|
82
|
+
subprocess.check_call(["git", "add", "--all"], cwd=path)
|
|
83
|
+
subprocess.check_call(["git", "commit", "-m", "chore: initial scaffold by devcore"], cwd=path)
|
|
84
|
+
print("Initialized local git repository.")
|
|
85
|
+
return "local"
|
|
86
|
+
except subprocess.CalledProcessError:
|
|
87
|
+
print("Git init failed.")
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
def render_template(template_name, context):
|
|
91
|
+
env = Environment(
|
|
92
|
+
loader=FileSystemLoader(TEMPLATE_DIR),
|
|
93
|
+
autoescape=select_autoescape()
|
|
94
|
+
)
|
|
95
|
+
template = env.get_template(template_name)
|
|
96
|
+
return template.render(context)
|
|
97
|
+
|
|
98
|
+
def write_file(path, content):
|
|
99
|
+
os.makedirs(os.path.dirname(path), exist_ok=True)
|
|
100
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
101
|
+
f.write(content)
|
|
102
|
+
|
|
103
|
+
def create_default_templates():
|
|
104
|
+
os.makedirs(TEMPLATE_DIR, exist_ok=True)
|
|
105
|
+
defaults = {
|
|
106
|
+
"README.md.j2": "# {{ name }}\n\nClient: {{ client_name }}\nType: {{ project_type }}\nStack: {{ stack }}\n\nGenerated by DevCore CLI.\n",
|
|
107
|
+
".env.example.j2": "APP_NAME={{ name }}\nCLIENT={{ client_name }}\nSTACK={{ stack }}\n",
|
|
108
|
+
"docker-compose.yml.j2": "version: '3.7'\nservices:\n app:\n image: alpine:3.17\n command: sleep infinity\n volumes:\n - ./:/workspace\n working_dir: /workspace\n"
|
|
109
|
+
}
|
|
110
|
+
for filename, content in defaults.items():
|
|
111
|
+
path = os.path.join(TEMPLATE_DIR, filename)
|
|
112
|
+
if not os.path.exists(path):
|
|
113
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
114
|
+
f.write(content)
|
|
115
|
+
|
|
116
|
+
def create_project_structure(base_path, context):
|
|
117
|
+
os.makedirs(base_path, exist_ok=True)
|
|
118
|
+
for file in ["README.md.j2", ".env.example.j2", "docker-compose.yml.j2"]:
|
|
119
|
+
output_name = file.replace(".j2", "")
|
|
120
|
+
rendered = render_template(file, context)
|
|
121
|
+
write_file(os.path.join(base_path, output_name), rendered)
|
|
122
|
+
write_file(os.path.join(base_path, "src", "hello.txt"), f"This is {context['name']} scaffolded by devcore.\n")
|
|
123
|
+
|
|
124
|
+
def cmd_new_project(args):
|
|
125
|
+
name = args.name or f"{args.client}-{args.type}"
|
|
126
|
+
project_folder = os.path.join(os.getcwd(), name.replace(" ", "-"))
|
|
127
|
+
|
|
128
|
+
if os.path.exists(project_folder) and not args.force:
|
|
129
|
+
print(f"Error: {project_folder} exists. Use --force to overwrite.")
|
|
130
|
+
sys.exit(1)
|
|
131
|
+
if os.path.exists(project_folder) and args.force:
|
|
132
|
+
shutil.rmtree(project_folder)
|
|
133
|
+
|
|
134
|
+
create_default_templates()
|
|
135
|
+
context = {
|
|
136
|
+
"name": name,
|
|
137
|
+
"client_name": args.client,
|
|
138
|
+
"project_type": args.type,
|
|
139
|
+
"stack": args.stack or "default",
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
print(f"Creating project '{name}'...")
|
|
143
|
+
create_project_structure(project_folder, context)
|
|
144
|
+
|
|
145
|
+
repo_marker = None
|
|
146
|
+
if args.init_git:
|
|
147
|
+
repo_marker = init_git_repo(project_folder)
|
|
148
|
+
|
|
149
|
+
ensure_db()
|
|
150
|
+
add_project_to_db(name, args.client, args.type, args.stack or "default", project_folder, repo_url=None)
|
|
151
|
+
print(f"Project created at {project_folder}\nDatabase updated.")
|
|
152
|
+
|
|
153
|
+
def cmd_list_projects(_args):
|
|
154
|
+
ensure_db()
|
|
155
|
+
conn = sqlite3.connect(DB_PATH)
|
|
156
|
+
cur = conn.cursor()
|
|
157
|
+
cur.execute("SELECT id, name, client_name, project_type, stack, path, status, created_at FROM projects ORDER BY id DESC")
|
|
158
|
+
rows = cur.fetchall()
|
|
159
|
+
if not rows:
|
|
160
|
+
print("No projects found.")
|
|
161
|
+
return
|
|
162
|
+
for r in rows:
|
|
163
|
+
print(f"[{r[0]}] {r[1]} ({r[2]}) — {r[3]} — {r[6]} — {r[7]}")
|
|
164
|
+
|
|
165
|
+
def build_parser():
|
|
166
|
+
parser = argparse.ArgumentParser(prog="devcore", description="DevCore CLI with Template Engine")
|
|
167
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
168
|
+
|
|
169
|
+
new_parser = subparsers.add_parser("new", help="Create new resource")
|
|
170
|
+
new_sub = new_parser.add_subparsers(dest="subcommand")
|
|
171
|
+
|
|
172
|
+
proj = new_sub.add_parser("project", help="Create project scaffold")
|
|
173
|
+
proj.add_argument("--type", required=True, choices=["wordpress", "laravel", "nextjs", "api"], help="Project type")
|
|
174
|
+
proj.add_argument("--client", required=True, help="Client name")
|
|
175
|
+
proj.add_argument("--name", required=False, help="Project name")
|
|
176
|
+
proj.add_argument("--stack", required=False, help="Stack info")
|
|
177
|
+
proj.add_argument("--init-git", action="store_true", help="Initialize git repo")
|
|
178
|
+
proj.add_argument("--force", action="store_true", help="Overwrite existing folder")
|
|
179
|
+
proj.set_defaults(func=cmd_new_project)
|
|
180
|
+
|
|
181
|
+
list_parser = subparsers.add_parser("list", help="List projects")
|
|
182
|
+
list_parser.set_defaults(func=cmd_list_projects)
|
|
183
|
+
|
|
184
|
+
# ---------------------------
|
|
185
|
+
# GitHub Integration Commands
|
|
186
|
+
# ---------------------------
|
|
187
|
+
login_parser = subparsers.add_parser("login", help="Login ke layanan eksternal")
|
|
188
|
+
login_sub = login_parser.add_subparsers(dest="service")
|
|
189
|
+
|
|
190
|
+
github_login_parser = login_sub.add_parser("github", help="Login ke GitHub dengan Personal Access Token")
|
|
191
|
+
github_login_parser.set_defaults(func=lambda args: github_login())
|
|
192
|
+
|
|
193
|
+
github_parser = subparsers.add_parser("github", help="GitHub management commands")
|
|
194
|
+
github_sub = github_parser.add_subparsers(dest="action")
|
|
195
|
+
|
|
196
|
+
github_init_parser = github_sub.add_parser("init", help="Buat repo GitHub baru dan hubungkan ke project lokal")
|
|
197
|
+
github_init_parser.add_argument("project_name", help="Nama project (harus sudah dibuat sebelumnya)")
|
|
198
|
+
github_init_parser.set_defaults(func=lambda args: github_init(args.project_name, os.path.join(os.getcwd(), args.project_name)))
|
|
199
|
+
|
|
200
|
+
github_connect_parser = github_sub.add_parser("connect", help="Hubungkan project lokal ke repo GitHub yang sudah ada")
|
|
201
|
+
github_connect_parser.add_argument("project_name", help="Nama project lokal")
|
|
202
|
+
github_connect_parser.add_argument("repo_url", help="URL repo GitHub yang sudah ada")
|
|
203
|
+
github_connect_parser.set_defaults(func=lambda args: github_connect(os.path.join(os.getcwd(), args.project_name), args.repo_url))
|
|
204
|
+
|
|
205
|
+
# ---------------------------
|
|
206
|
+
# WordPress Project Generator
|
|
207
|
+
# ---------------------------
|
|
208
|
+
wp_parser = subparsers.add_parser("wp", help="WordPress utilities")
|
|
209
|
+
wp_sub = wp_parser.add_subparsers(dest="action")
|
|
210
|
+
|
|
211
|
+
# wp_init_parser = wp_sub.add_parser("init", help="Inisialisasi project WordPress baru")
|
|
212
|
+
# wp_init_parser.add_argument("project_name", help="Nama project WordPress")
|
|
213
|
+
# wp_init_parser.set_defaults(func=lambda args: init_wp_project(args.project_name))
|
|
214
|
+
wp_init_parser = wp_sub.add_parser("init", help="Inisialisasi project WordPress baru")
|
|
215
|
+
wp_init_parser.add_argument("project_name", help="Nama project WordPress")
|
|
216
|
+
wp_init_parser.add_argument(
|
|
217
|
+
"--include-setup",
|
|
218
|
+
action="store_true",
|
|
219
|
+
help="Jalankan setup plugin & theme otomatis setelah init selesai"
|
|
220
|
+
)
|
|
221
|
+
wp_init_parser.set_defaults(func=lambda args: init_wp_project(args.project_name, include_setup=args.include_setup))
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
wp_drop_parser = wp_sub.add_parser("dropdb", help="Hapus database, folder project, dan record dari DevCore")
|
|
226
|
+
wp_drop_parser.add_argument("project_name", help="Nama project WordPress yang ingin dihapus")
|
|
227
|
+
wp_drop_parser.set_defaults(func=lambda args: drop_wp_database(args.project_name))
|
|
228
|
+
|
|
229
|
+
wp_setup_parser = wp_sub.add_parser("setup", help="Setup plugin & theme WordPress sesuai devcore_project.json")
|
|
230
|
+
wp_setup_parser.add_argument("--generate", action="store_true", help="Buat ulang file devcore_project.json")
|
|
231
|
+
wp_setup_parser.add_argument("project_dir", nargs="?", default=".", help="Path direktori proyek WordPress")
|
|
232
|
+
wp_setup_parser.set_defaults(func=lambda args: generate_project_config(args.project_dir) if args.generate else cmd_wp_setup(args.project_dir))
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
# ---------------------------
|
|
236
|
+
# Environment Config Commands
|
|
237
|
+
# ---------------------------
|
|
238
|
+
config_parser = subparsers.add_parser("config", help="Kelola konfigurasi environment DevCore")
|
|
239
|
+
config_sub = config_parser.add_subparsers(dest="action")
|
|
240
|
+
|
|
241
|
+
config_reset_parser = config_sub.add_parser("reset", help="Hapus konfigurasi environment dan kembalikan ke default")
|
|
242
|
+
config_reset_parser.set_defaults(func=lambda args: cmd_reset_config())
|
|
243
|
+
|
|
244
|
+
config_rebuild_parser = config_sub.add_parser("rebuild", help="Hapus dan buat ulang file konfigurasi environment")
|
|
245
|
+
config_rebuild_parser.set_defaults(func=lambda args: rebuild_env_config())
|
|
246
|
+
|
|
247
|
+
return parser
|
|
248
|
+
|
|
249
|
+
def main():
|
|
250
|
+
global args
|
|
251
|
+
parser = build_parser()
|
|
252
|
+
args = parser.parse_args()
|
|
253
|
+
if not args.command:
|
|
254
|
+
parser.print_help()
|
|
255
|
+
sys.exit(0)
|
|
256
|
+
|
|
257
|
+
if hasattr(args, "func"):
|
|
258
|
+
args.func(args)
|
|
259
|
+
else:
|
|
260
|
+
print("Invalid command.")
|
|
261
|
+
|
|
262
|
+
if __name__ == "__main__":
|
|
263
|
+
main()
|
|
264
|
+
|
|
265
|
+
|
|
@@ -2,11 +2,13 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name="devcore-cli",
|
|
5
|
-
version="1.0.
|
|
5
|
+
version="1.0.4",
|
|
6
6
|
author="Puji Ermanto | <Engineer>",
|
|
7
7
|
author_email="puji@gmail.com",
|
|
8
8
|
description="DevCore — WordPress & Laravel project automation CLI",
|
|
9
|
-
packages=find_packages(),
|
|
9
|
+
packages=find_packages(include=["core", "core.*"]),
|
|
10
|
+
package_dir={"core": "core"},
|
|
11
|
+
py_modules=["devcore"], # pastikan devcore.py ikut
|
|
10
12
|
include_package_data=True,
|
|
11
13
|
install_requires=[
|
|
12
14
|
"jinja2>=3.1.2",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
core
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|