devcore-cli 1.0.1__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/PKG-INFO +13 -0
- devcore_cli-1.0.1/README.md +116 -0
- devcore_cli-1.0.1/core/__init__.py +0 -0
- devcore_cli-1.0.1/core/command_config.py +11 -0
- devcore_cli-1.0.1/core/command_wp_setup.py +117 -0
- devcore_cli-1.0.1/core/db.py +43 -0
- devcore_cli-1.0.1/core/env_manager.py +188 -0
- devcore_cli-1.0.1/core/github_integration.py +111 -0
- devcore_cli-1.0.1/core/template_engine.py +17 -0
- devcore_cli-1.0.1/core/wp_dropdb.py +75 -0
- devcore_cli-1.0.1/core/wp_init.py +286 -0
- devcore_cli-1.0.1/devcore_cli.egg-info/PKG-INFO +13 -0
- devcore_cli-1.0.1/devcore_cli.egg-info/SOURCES.txt +18 -0
- devcore_cli-1.0.1/devcore_cli.egg-info/dependency_links.txt +1 -0
- devcore_cli-1.0.1/devcore_cli.egg-info/entry_points.txt +2 -0
- devcore_cli-1.0.1/devcore_cli.egg-info/requires.txt +1 -0
- devcore_cli-1.0.1/devcore_cli.egg-info/top_level.txt +1 -0
- devcore_cli-1.0.1/pyproject.toml +3 -0
- devcore_cli-1.0.1/setup.cfg +4 -0
- devcore_cli-1.0.1/setup.py +20 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devcore-cli
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: DevCore โ WordPress & Laravel project automation CLI
|
|
5
|
+
Author: Puji Ermanto | <Engineer>
|
|
6
|
+
Author-email: puji@gmail.com
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Requires-Dist: jinja2>=3.1.2
|
|
9
|
+
Dynamic: author
|
|
10
|
+
Dynamic: author-email
|
|
11
|
+
Dynamic: requires-dist
|
|
12
|
+
Dynamic: requires-python
|
|
13
|
+
Dynamic: summary
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# ๐ง DevCore CLI
|
|
2
|
+
|
|
3
|
+
DevCore adalah sistem otomatisasi untuk setup, konfigurasi, dan deployment stack WordPress modern melalui Command Line Interface (CLI).
|
|
4
|
+
Didesain untuk developer yang ingin mempercepat workflow WordPress Development, mulai dari inisialisasi proyek, konfigurasi environment, hingga sinkronisasi GitHub โ semua hanya lewat terminal.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## ๐ Fitur Utama
|
|
9
|
+
|
|
10
|
+
- โ๏ธ **WordPress Auto Installer & Setup**
|
|
11
|
+
Buat project WordPress siap-pakai hanya dengan satu perintah.
|
|
12
|
+
|
|
13
|
+
- ๐งฉ **Template Builder**
|
|
14
|
+
Dukung stack: `WordPress + WooCommerce + Elementor`.
|
|
15
|
+
|
|
16
|
+
- ๐พ **Database Handler (SQLite)**
|
|
17
|
+
Menyimpan metadata project dan konfigurasi CLI dengan aman.
|
|
18
|
+
|
|
19
|
+
- ๐ **Konfigurasi Environment Otomatis**
|
|
20
|
+
Termasuk rebuild & reset config.
|
|
21
|
+
|
|
22
|
+
- ๐ **Auto Sync ke GitHub**
|
|
23
|
+
Login GitHub langsung dari CLI.
|
|
24
|
+
|
|
25
|
+
- ๐งฑ **Modular CLI Structure**
|
|
26
|
+
Setiap perintah terpisah secara modular di direktori `core/`.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## โก Perintah Dasar DevCore
|
|
31
|
+
|
|
32
|
+
#### 1๏ธโฃ Login GitHub terlebih dahulu
|
|
33
|
+
```bash
|
|
34
|
+
devcore login github
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
#### Setup project
|
|
38
|
+
```bash
|
|
39
|
+
devcore wp setup --generate
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
2๏ธโฃ Membuat template awal
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
devcore new project --type wordpress --client "New-Commerce-Project" --stack "wordpress+woo"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3๏ธโฃ Build WordPress Project
|
|
49
|
+
```bash
|
|
50
|
+
devcore wp init New-Commerce-Project
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
4๏ธโฃ Reset atau Rebuild Konfigurasi
|
|
54
|
+
```bash
|
|
55
|
+
devcore config rebuild
|
|
56
|
+
devcore config reset
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
5๏ธโฃ Menghapus Database Project
|
|
60
|
+
```bash
|
|
61
|
+
del devcore_projects.db
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
#### Setup WordPress Plugins & Themes
|
|
65
|
+
Installs plugins and themes automatically using WP-CLI based on configuration files.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
devcore wp init New-Commerce-Project --include-setup
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
๐ Struktur Direktori DevCore
|
|
72
|
+
```bash
|
|
73
|
+
dev-core-system/
|
|
74
|
+
โ
|
|
75
|
+
โโโ core/
|
|
76
|
+
โ โโโ command_config.py
|
|
77
|
+
โ โโโ command_new_setup.py
|
|
78
|
+
โ โโโ db.py
|
|
79
|
+
โ โโโ env_manager.py
|
|
80
|
+
โ โโโ wp_init.py
|
|
81
|
+
โ โโโ wp_dropdb.py
|
|
82
|
+
โ โโโ github_integration.py
|
|
83
|
+
โ โโโ template_engine.py
|
|
84
|
+
โ
|
|
85
|
+
โโโ templates/
|
|
86
|
+
โ โโโ .env.example (autogenerate)
|
|
87
|
+
โ โโโ docker-compose.yml (autogenerate)
|
|
88
|
+
โ โโโ README.md (autogenerate)
|
|
89
|
+
โ
|
|
90
|
+
โโโ .devcore.json
|
|
91
|
+
โโโ devcore_projects.db
|
|
92
|
+
โโโ devcore
|
|
93
|
+
โโโ devcore.cmd
|
|
94
|
+
โโโ README.md
|
|
95
|
+
โโโ DOCUMENTATION.md
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
๐งญ Roadmap Singkat
|
|
99
|
+
| Fase | Deskripsi | Status |
|
|
100
|
+
| ------- | -------------------------------------- | -------------- |
|
|
101
|
+
| Phase 1 | Core CLI & Config Handler | โ
Selesai |
|
|
102
|
+
| Phase 2 | WordPress Stack Builder | ๐ง In Progress |
|
|
103
|
+
| Phase 3 | Integration Layer (GitHub, VPS Deploy) | โณ Planned |
|
|
104
|
+
| Phase 4 | Automation & Backup | โณ Planned |
|
|
105
|
+
| Phase 5 | DevCore Cloud Dashboard | ๐งฉ Research |
|
|
106
|
+
<img width="1024" height="1536" alt="devcore-system-roadmap" src="https://github.com/user-attachments/assets/a4b64b39-068e-4ef2-8044-b2aadf9d4b39" />
|
|
107
|
+
|
|
108
|
+
๐ Lisensi
|
|
109
|
+
|
|
110
|
+
MIT License ยฉ 2025 โ [DevCore Project Team > Puji Ermanto<pujiermanto@gmail.com>]
|
|
111
|
+
|
|
112
|
+
๐ฌ Kontribusi
|
|
113
|
+
|
|
114
|
+
Pull Request, Issue, dan Feedback selalu terbuka.
|
|
115
|
+
Silakan buat branch baru sebelum commit ke main.
|
|
116
|
+
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# core/command_config.py
|
|
2
|
+
import os
|
|
3
|
+
from core.env_manager import CONFIG_FILE
|
|
4
|
+
|
|
5
|
+
def cmd_reset_config():
|
|
6
|
+
"""Menghapus file konfigurasi DevCore"""
|
|
7
|
+
if os.path.exists(CONFIG_FILE):
|
|
8
|
+
os.remove(CONFIG_FILE)
|
|
9
|
+
print(f"โ๏ธ Konfigurasi environment berhasil direset: {CONFIG_FILE}")
|
|
10
|
+
else:
|
|
11
|
+
print("โ ๏ธ Tidak ada file konfigurasi yang ditemukan untuk dihapus.")
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# core/command_wp_setup.py
|
|
2
|
+
import os
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
GLOBAL_CONFIG = Path(__file__).resolve().parent.parent / ".devcore.json"
|
|
8
|
+
|
|
9
|
+
def load_global_config():
|
|
10
|
+
if GLOBAL_CONFIG.exists():
|
|
11
|
+
with open(GLOBAL_CONFIG, "r") as f:
|
|
12
|
+
return json.load(f)
|
|
13
|
+
return {}
|
|
14
|
+
|
|
15
|
+
def load_project_config(project_dir):
|
|
16
|
+
project_config = Path(project_dir) / "devcore_project.json"
|
|
17
|
+
if project_config.exists():
|
|
18
|
+
with open(project_config, "r") as f:
|
|
19
|
+
return json.load(f)
|
|
20
|
+
return {}
|
|
21
|
+
|
|
22
|
+
def run_wp_cli(commands, cwd):
|
|
23
|
+
"""Menjalankan WP-CLI command di direktori WordPress project"""
|
|
24
|
+
for cmd in commands:
|
|
25
|
+
print(f"๐ Menjalankan: wp {cmd}")
|
|
26
|
+
try:
|
|
27
|
+
subprocess.run(["wp"] + cmd.split(), cwd=cwd, check=True)
|
|
28
|
+
except subprocess.CalledProcessError as e:
|
|
29
|
+
print(f"โ Gagal menjalankan: wp {cmd} ({e})")
|
|
30
|
+
|
|
31
|
+
def cmd_wp_setup(project_dir="."):
|
|
32
|
+
"""Menginstall plugin & theme sesuai konfigurasi"""
|
|
33
|
+
print("๐ Membaca konfigurasi DevCore...")
|
|
34
|
+
global_config = load_global_config()
|
|
35
|
+
project_config = load_project_config(project_dir)
|
|
36
|
+
|
|
37
|
+
plugins = project_config.get("plugins") or global_config.get("default_plugins", [])
|
|
38
|
+
themes = project_config.get("themes") or global_config.get("default_themes", [])
|
|
39
|
+
|
|
40
|
+
if not plugins and not themes:
|
|
41
|
+
print("โ ๏ธ Tidak ada plugin atau theme yang terdaftar untuk diinstall.")
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
print(f"๐ฆ Plugin terdeteksi: {plugins}")
|
|
45
|
+
print(f"๐จ Theme terdeteksi: {themes}")
|
|
46
|
+
|
|
47
|
+
# Jalankan instalasi plugin
|
|
48
|
+
plugin_cmds = [f"plugin install {p} --activate" for p in plugins]
|
|
49
|
+
theme_cmds = []
|
|
50
|
+
for t in themes:
|
|
51
|
+
if t == "blocksy-child":
|
|
52
|
+
# Lewati install, nanti dibuat manual
|
|
53
|
+
continue
|
|
54
|
+
theme_cmds.append(f"theme install {t} --activate")
|
|
55
|
+
|
|
56
|
+
run_wp_cli(plugin_cmds + theme_cmds, cwd=project_dir)
|
|
57
|
+
|
|
58
|
+
print("โ
Instalasi plugin & theme selesai!")
|
|
59
|
+
|
|
60
|
+
# Auto-generate Blocksy Child theme jika diperlukan
|
|
61
|
+
blocksy_child_dir = Path(project_dir) / "wp-content" / "themes" / "blocksy-child"
|
|
62
|
+
if "blocksy-child" in themes and not blocksy_child_dir.exists():
|
|
63
|
+
print("๐งฑ Membuat Blocksy Child theme otomatis...")
|
|
64
|
+
os.makedirs(blocksy_child_dir, exist_ok=True)
|
|
65
|
+
|
|
66
|
+
style_css = """/*
|
|
67
|
+
Theme Name: Blocksy Child
|
|
68
|
+
Template: blocksy
|
|
69
|
+
Author: DevCore System
|
|
70
|
+
Description: Child theme untuk kustomisasi Blocksy.
|
|
71
|
+
Version: 1.0
|
|
72
|
+
*/
|
|
73
|
+
@import url("../blocksy/style.css");
|
|
74
|
+
"""
|
|
75
|
+
functions_php = """<?php
|
|
76
|
+
add_action('wp_enqueue_scripts', function() {
|
|
77
|
+
wp_enqueue_style('blocksy-child-style', get_stylesheet_uri());
|
|
78
|
+
}, 20);
|
|
79
|
+
"""
|
|
80
|
+
with open(blocksy_child_dir / "style.css", "w", encoding="utf-8") as f:
|
|
81
|
+
f.write(style_css)
|
|
82
|
+
|
|
83
|
+
with open(blocksy_child_dir / "functions.php", "w", encoding="utf-8") as f:
|
|
84
|
+
f.write(functions_php)
|
|
85
|
+
|
|
86
|
+
print("โ
Blocksy Child theme berhasil dibuat.")
|
|
87
|
+
subprocess.run(["wp", "theme", "activate", "blocksy-child"], cwd=project_dir)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def generate_project_config(project_dir="."):
|
|
92
|
+
"""Generate ulang devcore_project.json berdasarkan input user atau default global"""
|
|
93
|
+
print("๐งฑ Membuat ulang devcore_project.json ...")
|
|
94
|
+
|
|
95
|
+
global_config = load_global_config()
|
|
96
|
+
|
|
97
|
+
default_plugins = global_config.get("default_plugins", ["woocommerce"])
|
|
98
|
+
default_themes = global_config.get("default_themes", ["blocksy", "blocksy-child"])
|
|
99
|
+
|
|
100
|
+
project_name = input("๐ Nama proyek: ") or "New-Project"
|
|
101
|
+
plugins_input = input(f"๐ Plugin (pisahkan koma, default: {', '.join(default_plugins)}): ").strip()
|
|
102
|
+
themes_input = input(f"๐จ Theme (pisahkan koma, default: {', '.join(default_themes)}): ").strip()
|
|
103
|
+
|
|
104
|
+
plugins = [p.strip() for p in plugins_input.split(",")] if plugins_input else default_plugins
|
|
105
|
+
themes = [t.strip() for t in themes_input.split(",")] if themes_input else default_themes
|
|
106
|
+
|
|
107
|
+
config_data = {
|
|
108
|
+
"project_name": project_name,
|
|
109
|
+
"plugins": plugins,
|
|
110
|
+
"themes": themes
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
config_path = Path(project_dir) / "devcore_project.json"
|
|
114
|
+
with open(config_path, "w", encoding="utf-8") as f:
|
|
115
|
+
json.dump(config_data, f, indent=2)
|
|
116
|
+
|
|
117
|
+
print(f"โ
File devcore_project.json berhasil dibuat di {config_path}")
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# core/db.py
|
|
2
|
+
import os
|
|
3
|
+
import sqlite3
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
DB_PATH = os.path.join(os.getcwd(), "devcore_projects.db")
|
|
7
|
+
|
|
8
|
+
def ensure_db():
|
|
9
|
+
conn = sqlite3.connect(DB_PATH)
|
|
10
|
+
cur = conn.cursor()
|
|
11
|
+
cur.execute("""
|
|
12
|
+
CREATE TABLE IF NOT EXISTS projects (
|
|
13
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
14
|
+
name TEXT,
|
|
15
|
+
client_name TEXT,
|
|
16
|
+
project_type TEXT,
|
|
17
|
+
stack TEXT,
|
|
18
|
+
path TEXT,
|
|
19
|
+
repo_url TEXT,
|
|
20
|
+
status TEXT,
|
|
21
|
+
created_at TEXT
|
|
22
|
+
)
|
|
23
|
+
""")
|
|
24
|
+
conn.commit()
|
|
25
|
+
conn.close()
|
|
26
|
+
|
|
27
|
+
def add_project(name, client_name, project_type, stack, path, repo_url=None, status="created"):
|
|
28
|
+
ensure_db()
|
|
29
|
+
conn = sqlite3.connect(DB_PATH)
|
|
30
|
+
cur = conn.cursor()
|
|
31
|
+
cur.execute("""
|
|
32
|
+
INSERT INTO projects (name, client_name, project_type, stack, path, repo_url, status, created_at)
|
|
33
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
34
|
+
""", (name, client_name, project_type, stack, path, repo_url, status, datetime.utcnow().isoformat()))
|
|
35
|
+
conn.commit()
|
|
36
|
+
conn.close()
|
|
37
|
+
|
|
38
|
+
def update_repo_url(name, repo_url):
|
|
39
|
+
conn = sqlite3.connect(DB_PATH)
|
|
40
|
+
cur = conn.cursor()
|
|
41
|
+
cur.execute("UPDATE projects SET repo_url = ?, status = 'pushed' WHERE name = ?", (repo_url, name))
|
|
42
|
+
conn.commit()
|
|
43
|
+
conn.close()
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import shutil
|
|
4
|
+
import platform
|
|
5
|
+
import subprocess
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
CONFIG_FILE = Path(__file__).resolve().parent.parent / ".devcore.json"
|
|
9
|
+
|
|
10
|
+
def get_default_paths():
|
|
11
|
+
"""Tentukan path default berdasarkan sistem operasi"""
|
|
12
|
+
system = platform.system().lower()
|
|
13
|
+
|
|
14
|
+
if "windows" in system:
|
|
15
|
+
return {
|
|
16
|
+
"xampp": Path("C:/xampp/htdocs"),
|
|
17
|
+
"laragon": Path("C:/laragon/www"),
|
|
18
|
+
"laradock": Path("C:/laradock/projects")
|
|
19
|
+
}
|
|
20
|
+
elif "darwin" in system: # macOS
|
|
21
|
+
return {
|
|
22
|
+
"xampp": Path("/Applications/XAMPP/htdocs"),
|
|
23
|
+
"laragon": Path.home() / "Sites/laragon",
|
|
24
|
+
"laradock": Path.home() / "Sites/laradock"
|
|
25
|
+
}
|
|
26
|
+
else: # Linux
|
|
27
|
+
return {
|
|
28
|
+
"xampp": Path("/opt/lampp/htdocs"),
|
|
29
|
+
"laragon": Path.home() / "Projects/laragon",
|
|
30
|
+
"laradock": Path.home() / "Projects/laradock"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
def load_env_config():
|
|
34
|
+
"""Muat konfigurasi environment, jika belum ada buat otomatis"""
|
|
35
|
+
defaults = get_default_paths()
|
|
36
|
+
|
|
37
|
+
if CONFIG_FILE.exists():
|
|
38
|
+
with open(CONFIG_FILE, "r") as f:
|
|
39
|
+
config = json.load(f)
|
|
40
|
+
else:
|
|
41
|
+
config = {k: str(v) for k, v in defaults.items()}
|
|
42
|
+
save_env_config(config)
|
|
43
|
+
|
|
44
|
+
# Pastikan semua path ada
|
|
45
|
+
for key, path_str in config.items():
|
|
46
|
+
path = Path(path_str)
|
|
47
|
+
if not path.exists():
|
|
48
|
+
path.mkdir(parents=True, exist_ok=True)
|
|
49
|
+
print(f"๐ Path '{path}' dibuat otomatis untuk {key}")
|
|
50
|
+
|
|
51
|
+
return config
|
|
52
|
+
|
|
53
|
+
def save_env_config(config):
|
|
54
|
+
with open(CONFIG_FILE, "w") as f:
|
|
55
|
+
json.dump(config, f, indent=4)
|
|
56
|
+
print(f"โ
Konfigurasi environment tersimpan di {CONFIG_FILE}")
|
|
57
|
+
|
|
58
|
+
def choose_environment():
|
|
59
|
+
"""Pilih environment dan pastikan path-nya ada"""
|
|
60
|
+
config = load_env_config()
|
|
61
|
+
|
|
62
|
+
print("Pilih environment lokal:")
|
|
63
|
+
print(f"[1] XAMPP ({config['xampp']})")
|
|
64
|
+
print(f"[2] Laragon ({config['laragon']})")
|
|
65
|
+
print(f"[3] Laradock ({config['laradock']})")
|
|
66
|
+
|
|
67
|
+
choice = input("> ").strip()
|
|
68
|
+
if choice == "1":
|
|
69
|
+
env, base = "xampp", Path(config["xampp"])
|
|
70
|
+
elif choice == "2":
|
|
71
|
+
env, base = "laragon", Path(config["laragon"])
|
|
72
|
+
elif choice == "3":
|
|
73
|
+
env, base = "laradock", Path(config["laradock"])
|
|
74
|
+
else:
|
|
75
|
+
print("โ Pilihan tidak valid, default ke current directory.")
|
|
76
|
+
env, base = "unknown", Path.cwd()
|
|
77
|
+
|
|
78
|
+
base.mkdir(parents=True, exist_ok=True)
|
|
79
|
+
print(f"๐ Environment dipilih: {env} โ {base}")
|
|
80
|
+
return env, base
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def set_custom_env():
|
|
84
|
+
config = load_env_config()
|
|
85
|
+
print("๐ ๏ธ Konfigurasi environment custom:")
|
|
86
|
+
for key in config.keys():
|
|
87
|
+
new_path = input(f"Masukkan path untuk {key} (Enter untuk skip): ").strip()
|
|
88
|
+
if new_path:
|
|
89
|
+
config[key] = new_path.replace("\\", "/")
|
|
90
|
+
save_env_config(config)
|
|
91
|
+
|
|
92
|
+
def rebuild_env_config():
|
|
93
|
+
"""Hapus dan buat ulang file konfigurasi environment DevCore"""
|
|
94
|
+
if CONFIG_FILE.exists():
|
|
95
|
+
CONFIG_FILE.unlink()
|
|
96
|
+
print("๐๏ธ File konfigurasi lama dihapus.")
|
|
97
|
+
|
|
98
|
+
defaults = {k: str(v) for k, v in get_default_paths().items()}
|
|
99
|
+
save_env_config(defaults)
|
|
100
|
+
print("โ
Konfigurasi default berhasil dibuat ulang.")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_mysql_path(env_name: str) -> Path | None:
|
|
104
|
+
"""Kembalikan path MySQL sesuai environment"""
|
|
105
|
+
system = platform.system().lower()
|
|
106
|
+
|
|
107
|
+
if "windows" in system:
|
|
108
|
+
if env_name == "xampp":
|
|
109
|
+
return Path("C:/xampp/mysql/bin")
|
|
110
|
+
elif env_name == "laragon":
|
|
111
|
+
# deteksi otomatis versi MySQL (jika ada)
|
|
112
|
+
base = Path("C:/laragon/bin/mysql")
|
|
113
|
+
if base.exists():
|
|
114
|
+
versions = sorted(base.glob("mysql*/bin"), reverse=True)
|
|
115
|
+
if versions:
|
|
116
|
+
return versions[0]
|
|
117
|
+
return base / "mysql-8.0.30-winx64/bin" # fallback
|
|
118
|
+
elif env_name == "laradock":
|
|
119
|
+
return Path("C:/laradock/mysql/bin")
|
|
120
|
+
else:
|
|
121
|
+
# Mac/Linux
|
|
122
|
+
if env_name == "xampp":
|
|
123
|
+
return Path("/opt/lampp/bin")
|
|
124
|
+
elif env_name == "laradock":
|
|
125
|
+
return Path.home() / "Projects/laradock/mysql/bin"
|
|
126
|
+
|
|
127
|
+
return None
|
|
128
|
+
|
|
129
|
+
def add_to_system_path(path_to_add: Path):
|
|
130
|
+
"""Tambahkan folder ke Environment PATH (permanent)"""
|
|
131
|
+
system = platform.system().lower()
|
|
132
|
+
path_str = str(path_to_add.resolve())
|
|
133
|
+
|
|
134
|
+
if not path_to_add.exists():
|
|
135
|
+
print(f"โ ๏ธ Path tidak ditemukan: {path_to_add}")
|
|
136
|
+
return False
|
|
137
|
+
|
|
138
|
+
if "windows" in system:
|
|
139
|
+
# Ambil PATH sekarang dengan ekspansi variabel
|
|
140
|
+
current_path = os.environ.get("PATH", "")
|
|
141
|
+
if path_str in current_path:
|
|
142
|
+
print(f"โ๏ธ PATH sudah mengandung: {path_str}")
|
|
143
|
+
return True
|
|
144
|
+
|
|
145
|
+
new_path = f"{current_path};{path_str}"
|
|
146
|
+
|
|
147
|
+
try:
|
|
148
|
+
subprocess.run(f'setx PATH "{new_path}"', shell=True, check=True)
|
|
149
|
+
print(f"โ
PATH berhasil ditambahkan di Windows: {path_str}")
|
|
150
|
+
except subprocess.CalledProcessError:
|
|
151
|
+
print(f"โ Gagal menambahkan PATH ke Windows.")
|
|
152
|
+
elif "darwin" in system or "linux" in system:
|
|
153
|
+
shell_rc = Path.home() / (".zshrc" if Path.home().joinpath(".zshrc").exists() else ".bashrc")
|
|
154
|
+
with open(shell_rc, "a") as f:
|
|
155
|
+
f.write(f'\n# Added by DevCore setup\nexport PATH="$PATH:{path_str}"\n')
|
|
156
|
+
print(f"โ
PATH ditambahkan ke {shell_rc}: {path_str}")
|
|
157
|
+
else:
|
|
158
|
+
print("โ ๏ธ Sistem operasi tidak dikenali, PATH tidak diubah.")
|
|
159
|
+
return False
|
|
160
|
+
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def detect_mysql_cli():
|
|
165
|
+
"""Cari lokasi file mysql.exe / mysql CLI di environment umum"""
|
|
166
|
+
# 1๏ธโฃ Coba cari di PATH sistem
|
|
167
|
+
mysql_path = shutil.which("mysql")
|
|
168
|
+
if mysql_path:
|
|
169
|
+
return Path(mysql_path)
|
|
170
|
+
|
|
171
|
+
# 2๏ธโฃ Coba lokasi bawaan Laragon
|
|
172
|
+
laragon_mysql = Path("C:/laragon/bin/mysql")
|
|
173
|
+
if laragon_mysql.exists():
|
|
174
|
+
for version_dir in sorted(laragon_mysql.glob("mysql*/bin/mysql.exe"), reverse=True):
|
|
175
|
+
return version_dir
|
|
176
|
+
|
|
177
|
+
# 3๏ธโฃ Coba lokasi bawaan XAMPP
|
|
178
|
+
xampp_mysql = Path("C:/xampp/mysql/bin/mysql.exe")
|
|
179
|
+
if xampp_mysql.exists():
|
|
180
|
+
return xampp_mysql
|
|
181
|
+
|
|
182
|
+
# 4๏ธโฃ Coba lokasi global Linux / Mac
|
|
183
|
+
if platform.system() != "Windows":
|
|
184
|
+
for path in ["/usr/bin/mysql", "/usr/local/mysql/bin/mysql"]:
|
|
185
|
+
if Path(path).exists():
|
|
186
|
+
return Path(path)
|
|
187
|
+
|
|
188
|
+
return None
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
import subprocess
|
|
4
|
+
import requests
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
CONFIG_PATH = Path.home() / ".devcore" / "config.json"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
# ==============================
|
|
11
|
+
# Utility: Config Management
|
|
12
|
+
# ==============================
|
|
13
|
+
def load_config():
|
|
14
|
+
if not CONFIG_PATH.exists():
|
|
15
|
+
return {}
|
|
16
|
+
with open(CONFIG_PATH, "r") as f:
|
|
17
|
+
return json.load(f)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def save_config(data):
|
|
21
|
+
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
22
|
+
with open(CONFIG_PATH, "w") as f:
|
|
23
|
+
json.dump(data, f, indent=4)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# ==============================
|
|
27
|
+
# GitHub Login / Token Setup
|
|
28
|
+
# ==============================
|
|
29
|
+
def github_login():
|
|
30
|
+
print("Masukkan GitHub Personal Access Token (PAT):")
|
|
31
|
+
token = input("> ").strip()
|
|
32
|
+
if not token.startswith("ghp_") and not token.startswith("github_"):
|
|
33
|
+
print("โ ๏ธ Token tidak valid. Pastikan menggunakan format GitHub PAT.")
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
config = load_config()
|
|
37
|
+
config["github_token"] = token
|
|
38
|
+
save_config(config)
|
|
39
|
+
print("โ
Token GitHub disimpan di ~/.devcore/config.json")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# ==============================
|
|
43
|
+
# GitHub Repo Creation
|
|
44
|
+
# ==============================
|
|
45
|
+
def create_github_repo(repo_name, private=True, description=""):
|
|
46
|
+
config = load_config()
|
|
47
|
+
token = config.get("github_token")
|
|
48
|
+
if not token:
|
|
49
|
+
print("โ Belum login GitHub. Jalankan 'devcore login github' dulu.")
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
api_url = "https://api.github.com/user/repos"
|
|
53
|
+
headers = {"Authorization": f"token {token}"}
|
|
54
|
+
payload = {
|
|
55
|
+
"name": repo_name,
|
|
56
|
+
"private": private,
|
|
57
|
+
"description": description or f"Repository for {repo_name} with devcore system by puji",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
response = requests.post(api_url, headers=headers, json=payload)
|
|
61
|
+
if response.status_code == 201:
|
|
62
|
+
repo_data = response.json()
|
|
63
|
+
print(f"โ
Repository berhasil dibuat: {repo_data['html_url']}")
|
|
64
|
+
return repo_data["clone_url"]
|
|
65
|
+
else:
|
|
66
|
+
print("โ Gagal membuat repository:", response.text)
|
|
67
|
+
return None
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# ==============================
|
|
71
|
+
# Local Git Initialization
|
|
72
|
+
# ==============================
|
|
73
|
+
def init_local_git(project_path, repo_url):
|
|
74
|
+
try:
|
|
75
|
+
# Cek apakah sudah ada repo git
|
|
76
|
+
git_dir = Path(project_path) / ".git"
|
|
77
|
+
if not git_dir.exists():
|
|
78
|
+
subprocess.run(["git", "init"], cwd=project_path, check=True)
|
|
79
|
+
subprocess.run(["git", "add", "."], cwd=project_path, check=True)
|
|
80
|
+
subprocess.run(["git", "commit", "-m", "Initial commit"], cwd=project_path, check=True)
|
|
81
|
+
subprocess.run(["git", "branch", "-M", "main"], cwd=project_path, check=True)
|
|
82
|
+
else:
|
|
83
|
+
# Sudah ada repo, pastikan ada perubahan baru
|
|
84
|
+
subprocess.run(["git", "add", "."], cwd=project_path, check=True)
|
|
85
|
+
subprocess.run(["git", "commit", "-m", "Sync commit"], cwd=project_path)
|
|
86
|
+
|
|
87
|
+
# Set remote origin (replace kalau sudah ada)
|
|
88
|
+
subprocess.run(["git", "remote", "remove", "origin"], cwd=project_path, stderr=subprocess.DEVNULL)
|
|
89
|
+
subprocess.run(["git", "remote", "add", "origin", repo_url], cwd=project_path, check=True)
|
|
90
|
+
|
|
91
|
+
# Push ke GitHub
|
|
92
|
+
subprocess.run(["git", "push", "-u", "origin", "main"], cwd=project_path, check=True)
|
|
93
|
+
print("๐ Project berhasil di-push ke GitHub.")
|
|
94
|
+
except subprocess.CalledProcessError as e:
|
|
95
|
+
print(f"โ Gagal menjalankan git command: {e}")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# ==============================
|
|
100
|
+
# Public API for CLI
|
|
101
|
+
# ==============================
|
|
102
|
+
def github_init(project_name, project_path):
|
|
103
|
+
print(f"๐ง Membuat repository untuk project: {project_name}")
|
|
104
|
+
repo_url = create_github_repo(project_name)
|
|
105
|
+
if repo_url:
|
|
106
|
+
init_local_git(project_path, repo_url)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def github_connect(project_path, existing_repo_url):
|
|
110
|
+
print(f"๐ Menghubungkan project ke repo: {existing_repo_url}")
|
|
111
|
+
init_local_git(project_path, existing_repo_url)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# core/template_engine.py
|
|
2
|
+
from jinja2 import Environment, FileSystemLoader
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
TEMPLATE_DIR = Path.cwd() / "templates"
|
|
6
|
+
|
|
7
|
+
def render_readme(context):
|
|
8
|
+
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
|
|
9
|
+
template = env.get_template("README.md.j2")
|
|
10
|
+
return template.render(context)
|
|
11
|
+
|
|
12
|
+
def generate_readme(project_path, context):
|
|
13
|
+
output_path = Path(project_path) / "README.md"
|
|
14
|
+
readme_content = render_readme(context)
|
|
15
|
+
with open(output_path, "w", encoding="utf-8") as f:
|
|
16
|
+
f.write(readme_content)
|
|
17
|
+
print("๐งพ README.md otomatis dibuat.")
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# core/wp_dropdb.py
|
|
2
|
+
from core.env_manager import choose_environment
|
|
3
|
+
import os
|
|
4
|
+
import sqlite3
|
|
5
|
+
import subprocess
|
|
6
|
+
import shutil
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
DB_PATH = os.path.join(os.getcwd(), "devcore_projects.db")
|
|
10
|
+
|
|
11
|
+
def detect_env():
|
|
12
|
+
"""Deteksi environment (Docker / XAMPP / Unknown)"""
|
|
13
|
+
if Path("docker-compose.yml").exists():
|
|
14
|
+
return "docker"
|
|
15
|
+
elif "xampp" in str(Path.cwd()).lower() or "mysql" in str(Path.cwd()).lower():
|
|
16
|
+
return "xampp"
|
|
17
|
+
else:
|
|
18
|
+
return "unknown"
|
|
19
|
+
|
|
20
|
+
def confirm(prompt):
|
|
21
|
+
"""Konfirmasi interaktif sebelum eksekusi fatal"""
|
|
22
|
+
ans = input(f"{prompt} (y/n): ").strip().lower()
|
|
23
|
+
return ans == "y"
|
|
24
|
+
|
|
25
|
+
def drop_wp_database(project_name):
|
|
26
|
+
env = detect_env()
|
|
27
|
+
print(f"๐งฉ Detected environment: {env}")
|
|
28
|
+
|
|
29
|
+
db_name = f"{project_name}_db".replace("-", "_").lower()
|
|
30
|
+
|
|
31
|
+
# Konfirmasi dulu
|
|
32
|
+
print(f"โ ๏ธ Ini akan menghapus permanen database '{db_name}' dan folder project '{project_name}'")
|
|
33
|
+
if not confirm("Lanjutkan penghapusan?"):
|
|
34
|
+
print("โ Dibatalkan oleh pengguna.")
|
|
35
|
+
return
|
|
36
|
+
|
|
37
|
+
# Hapus database (Docker / XAMPP)
|
|
38
|
+
if env == "docker":
|
|
39
|
+
print(f"๐งจ Menghapus volume Docker untuk {db_name}...")
|
|
40
|
+
try:
|
|
41
|
+
subprocess.run(["docker-compose", "down", "-v"], check=True)
|
|
42
|
+
print("โ
Docker volume berhasil dihapus.")
|
|
43
|
+
except subprocess.CalledProcessError:
|
|
44
|
+
print("โ ๏ธ Gagal menghapus volume Docker.")
|
|
45
|
+
elif env == "xampp":
|
|
46
|
+
print(f"๐งจ Menghapus database lokal '{db_name}'...")
|
|
47
|
+
try:
|
|
48
|
+
subprocess.run(["mysql", "-u", "root", "-e", f"DROP DATABASE IF EXISTS {db_name};"], check=True)
|
|
49
|
+
print(f"โ
Database {db_name} berhasil dihapus dari MySQL.")
|
|
50
|
+
except FileNotFoundError:
|
|
51
|
+
print("โ ๏ธ MySQL CLI tidak ditemukan. Pastikan MySQL ada di PATH.")
|
|
52
|
+
else:
|
|
53
|
+
print("โ Tidak bisa mendeteksi environment database, dilewati.")
|
|
54
|
+
|
|
55
|
+
# Hapus folder project
|
|
56
|
+
project_path = Path.cwd() / project_name
|
|
57
|
+
if project_path.exists():
|
|
58
|
+
print(f"๐๏ธ Menghapus folder project: {project_path}")
|
|
59
|
+
shutil.rmtree(project_path, ignore_errors=True)
|
|
60
|
+
print("โ
Folder project berhasil dihapus.")
|
|
61
|
+
else:
|
|
62
|
+
print("โ ๏ธ Folder project tidak ditemukan, dilewati.")
|
|
63
|
+
|
|
64
|
+
# Hapus record dari SQLite
|
|
65
|
+
if os.path.exists(DB_PATH):
|
|
66
|
+
conn = sqlite3.connect(DB_PATH)
|
|
67
|
+
cur = conn.cursor()
|
|
68
|
+
cur.execute("DELETE FROM projects WHERE name = ?", (project_name,))
|
|
69
|
+
conn.commit()
|
|
70
|
+
conn.close()
|
|
71
|
+
print("๐งพ Record project dihapus dari devcore_projects.db.")
|
|
72
|
+
else:
|
|
73
|
+
print("โ ๏ธ File devcore_projects.db tidak ditemukan, dilewati.")
|
|
74
|
+
|
|
75
|
+
print(f"๐ฅ Cleanup project '{project_name}' selesai total!\n")
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
from core.github_integration import github_init
|
|
2
|
+
from core.db import add_project
|
|
3
|
+
from core.template_engine import generate_readme
|
|
4
|
+
from core.env_manager import choose_environment, get_mysql_path, add_to_system_path
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import subprocess
|
|
9
|
+
import zipfile
|
|
10
|
+
import requests
|
|
11
|
+
import shutil
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
def init_wp_project(project_name, include_setup=False):
|
|
15
|
+
# === 1. Pilih environment (xampp / laragon / laradock) ===
|
|
16
|
+
env, base_dir = choose_environment()
|
|
17
|
+
mysql_path = get_mysql_path(env)
|
|
18
|
+
|
|
19
|
+
# === 2. Setup MySQL path ===
|
|
20
|
+
if mysql_path:
|
|
21
|
+
print(f"๐ Mengecek PATH MySQL untuk {env}: {mysql_path}")
|
|
22
|
+
add_to_system_path(mysql_path)
|
|
23
|
+
mysql_executable = str(mysql_path / "mysql")
|
|
24
|
+
else:
|
|
25
|
+
print("โ ๏ธ Tidak menemukan lokasi MySQL untuk environment ini.")
|
|
26
|
+
mysql_executable = "mysql" # fallback
|
|
27
|
+
|
|
28
|
+
project_dir = base_dir / project_name
|
|
29
|
+
wp_zip_path = project_dir / "wordpress.zip"
|
|
30
|
+
wp_url = "https://wordpress.org/latest.zip"
|
|
31
|
+
|
|
32
|
+
print(f"๐ Membuat project WordPress di {env.upper()}: {project_dir}")
|
|
33
|
+
os.makedirs(project_dir, exist_ok=True)
|
|
34
|
+
|
|
35
|
+
# === 3. Download WordPress core ===
|
|
36
|
+
print("โฌ๏ธ Downloading WordPress core...")
|
|
37
|
+
r = requests.get(wp_url)
|
|
38
|
+
with open(wp_zip_path, "wb") as f:
|
|
39
|
+
f.write(r.content)
|
|
40
|
+
|
|
41
|
+
# === 4. Extract dan pindahkan isi ===
|
|
42
|
+
print("๐ฆ Ekstrak WordPress...")
|
|
43
|
+
with zipfile.ZipFile(wp_zip_path, "r") as zip_ref:
|
|
44
|
+
zip_ref.extractall(project_dir)
|
|
45
|
+
|
|
46
|
+
wp_src = project_dir / "wordpress"
|
|
47
|
+
if wp_src.exists():
|
|
48
|
+
for item in wp_src.iterdir():
|
|
49
|
+
shutil.move(str(item), str(project_dir / item.name))
|
|
50
|
+
shutil.rmtree(wp_src)
|
|
51
|
+
|
|
52
|
+
wp_zip_path.unlink(missing_ok=True)
|
|
53
|
+
|
|
54
|
+
# === 5. Struktur tambahan ===
|
|
55
|
+
print("๐งฉ Membuat struktur Dev Core tambahan...")
|
|
56
|
+
os.makedirs(project_dir / "src/themes", exist_ok=True)
|
|
57
|
+
os.makedirs(project_dir / "src/plugins", exist_ok=True)
|
|
58
|
+
|
|
59
|
+
# === 6. File .env ===
|
|
60
|
+
wp_home = f"http://{project_name}.test" if env == "laragon" else f"http://localhost/{project_name}"
|
|
61
|
+
wp_siteurl = f"{wp_home}/wp"
|
|
62
|
+
|
|
63
|
+
env_content = f"""# Environment WordPress
|
|
64
|
+
DB_NAME={project_name}_db
|
|
65
|
+
DB_USER=root
|
|
66
|
+
DB_PASSWORD=
|
|
67
|
+
DB_HOST=localhost
|
|
68
|
+
WP_HOME={wp_home}
|
|
69
|
+
WP_SITEURL={wp_siteurl}
|
|
70
|
+
"""
|
|
71
|
+
(project_dir / ".env").write_text(env_content)
|
|
72
|
+
|
|
73
|
+
# === 7. docker-compose.yml ===
|
|
74
|
+
docker_content = f"""version: '3.8'
|
|
75
|
+
services:
|
|
76
|
+
db:
|
|
77
|
+
image: mysql:5.7
|
|
78
|
+
container_name: {project_name}_db
|
|
79
|
+
environment:
|
|
80
|
+
MYSQL_ROOT_PASSWORD: root
|
|
81
|
+
MYSQL_DATABASE: {project_name}_db
|
|
82
|
+
volumes:
|
|
83
|
+
- ./db_data:/var/lib/mysql
|
|
84
|
+
ports:
|
|
85
|
+
- "3306:3306"
|
|
86
|
+
|
|
87
|
+
wordpress:
|
|
88
|
+
image: wordpress:latest
|
|
89
|
+
container_name: {project_name}_wp
|
|
90
|
+
depends_on:
|
|
91
|
+
- db
|
|
92
|
+
environment:
|
|
93
|
+
WORDPRESS_DB_HOST: db:3306
|
|
94
|
+
WORDPRESS_DB_USER: root
|
|
95
|
+
WORDPRESS_DB_PASSWORD: root
|
|
96
|
+
WORDPRESS_DB_NAME: {project_name}_db
|
|
97
|
+
ports:
|
|
98
|
+
- "8080:80"
|
|
99
|
+
volumes:
|
|
100
|
+
- ./:/var/www/html
|
|
101
|
+
"""
|
|
102
|
+
(project_dir / "docker-compose.yml").write_text(docker_content)
|
|
103
|
+
|
|
104
|
+
# === 8. Git init ===
|
|
105
|
+
print("๐ค Inisialisasi Git repository...")
|
|
106
|
+
subprocess.run(["git", "init"], cwd=project_dir, check=False)
|
|
107
|
+
subprocess.run(["git", "add", "."], cwd=project_dir, check=False)
|
|
108
|
+
subprocess.run(["git", "commit", "-m", "Initialize WordPress project"], cwd=project_dir, check=False)
|
|
109
|
+
subprocess.run(["git", "branch", "-M", "main"], cwd=project_dir, check=False)
|
|
110
|
+
|
|
111
|
+
# === 9. Push otomatis ke GitHub ===
|
|
112
|
+
print("๐ Menghubungkan ke GitHub...")
|
|
113
|
+
github_init(project_name, project_dir)
|
|
114
|
+
|
|
115
|
+
# === 10. Simpan metadata project ===
|
|
116
|
+
add_project(
|
|
117
|
+
name=project_name,
|
|
118
|
+
client_name="default",
|
|
119
|
+
project_type="wordpress",
|
|
120
|
+
stack="wordpress+docker",
|
|
121
|
+
path=str(project_dir),
|
|
122
|
+
repo_url=f"https://github.com/codesyariah122/{project_name}",
|
|
123
|
+
status="pushed"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
print("๐ Metadata project tersimpan di devcore_projects.db")
|
|
127
|
+
|
|
128
|
+
# === 11. Generate README ===
|
|
129
|
+
context = {
|
|
130
|
+
"name": project_name,
|
|
131
|
+
"client_name": "default",
|
|
132
|
+
"project_type": "wordpress",
|
|
133
|
+
"stack": "wordpress+docker",
|
|
134
|
+
"created_at": datetime.utcnow().isoformat()
|
|
135
|
+
}
|
|
136
|
+
generate_readme(project_dir, context)
|
|
137
|
+
|
|
138
|
+
# === 12. Optional: Buat database lokal ===
|
|
139
|
+
if env in ["xampp", "laragon"]:
|
|
140
|
+
db_name = project_name.lower().replace("-", "_").replace(" ", "_") + "_db"
|
|
141
|
+
print(f"๐งฉ Membuat database lokal '{db_name}'...")
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
subprocess.run([mysql_executable, "-u", "root", "-e", f"CREATE DATABASE IF NOT EXISTS {db_name};"], check=True)
|
|
145
|
+
print(f"โ
Database '{db_name}' berhasil dibuat di MySQL lokal.")
|
|
146
|
+
except FileNotFoundError:
|
|
147
|
+
print("โ ๏ธ MySQL CLI tidak ditemukan di PATH atau lokasi umum.")
|
|
148
|
+
except subprocess.CalledProcessError as e:
|
|
149
|
+
print(f"โ Gagal membuat database: {e}")
|
|
150
|
+
|
|
151
|
+
# === 12.1 Buat devcore_project.json default jika belum ada ===
|
|
152
|
+
config_path = project_dir / "devcore_project.json"
|
|
153
|
+
if not config_path.exists():
|
|
154
|
+
default_config = {
|
|
155
|
+
"project_name": project_name,
|
|
156
|
+
"plugins": ["woocommerce", "jetpack"],
|
|
157
|
+
"themes": ["blocksy", "blocksy-child"]
|
|
158
|
+
}
|
|
159
|
+
with open(config_path, "w", encoding="utf-8") as f:
|
|
160
|
+
import json
|
|
161
|
+
json.dump(default_config, f, indent=4)
|
|
162
|
+
print("๐งพ devcore_project.json default dibuat otomatis.")
|
|
163
|
+
else:
|
|
164
|
+
print("โ
devcore_project.json sudah ada, skip pembuatan.")
|
|
165
|
+
|
|
166
|
+
# === 13. Install plugin & theme dari devcore_project.json ===
|
|
167
|
+
install_plugins_and_themes(project_dir)
|
|
168
|
+
print("๐ WordPress project berhasil dibuat lengkap!\n")
|
|
169
|
+
|
|
170
|
+
def install_plugins_and_themes(project_dir):
|
|
171
|
+
"""Baca devcore_project.json lalu install plugin & theme sesuai daftar"""
|
|
172
|
+
import json
|
|
173
|
+
import shutil
|
|
174
|
+
|
|
175
|
+
config_path = project_dir / "devcore_project.json"
|
|
176
|
+
if not config_path.exists():
|
|
177
|
+
print("โ ๏ธ Tidak menemukan devcore_project.json, skip instalasi plugin/theme.")
|
|
178
|
+
return
|
|
179
|
+
|
|
180
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
181
|
+
config = json.load(f)
|
|
182
|
+
|
|
183
|
+
plugins = config.get("plugins", [])
|
|
184
|
+
themes = config.get("themes", [])
|
|
185
|
+
|
|
186
|
+
if not plugins and not themes:
|
|
187
|
+
print("โน๏ธ Tidak ada plugin atau theme untuk diinstall.")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
# === Cari wp-cli ===
|
|
191
|
+
wp_cli = shutil.which("wp")
|
|
192
|
+
if not wp_cli:
|
|
193
|
+
tools_dir = Path(__file__).resolve().parent.parent / "tools" / "wp-cli"
|
|
194
|
+
tools_dir.mkdir(parents=True, exist_ok=True)
|
|
195
|
+
wp_phar = tools_dir / "wp-cli.phar"
|
|
196
|
+
|
|
197
|
+
if not wp_phar.exists():
|
|
198
|
+
print("โฌ๏ธ WP-CLI belum ada. Mengunduh dari https://github.com/wp-cli/builds...")
|
|
199
|
+
url = "https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar"
|
|
200
|
+
r = requests.get(url, timeout=30)
|
|
201
|
+
wp_phar.write_bytes(r.content)
|
|
202
|
+
print(f"โ
WP-CLI berhasil diunduh ke {wp_phar}")
|
|
203
|
+
|
|
204
|
+
php_path = shutil.which("php")
|
|
205
|
+
if not php_path:
|
|
206
|
+
print("โ PHP CLI tidak ditemukan di PATH. Instalasi plugin/theme dibatalkan.")
|
|
207
|
+
return
|
|
208
|
+
|
|
209
|
+
wp_cli_cmd = [php_path, str(wp_phar)]
|
|
210
|
+
else:
|
|
211
|
+
wp_cli_cmd = [wp_cli]
|
|
212
|
+
|
|
213
|
+
# === Clear cache sebelum instalasi ===
|
|
214
|
+
print("๐งน Membersihkan cache WP-CLI...")
|
|
215
|
+
subprocess.run(wp_cli_cmd + ["cache", "clear"], cwd=project_dir, check=False)
|
|
216
|
+
|
|
217
|
+
# === Pastikan wp-config.php sudah ada ===
|
|
218
|
+
wp_config = project_dir / "wp-config.php"
|
|
219
|
+
if not wp_config.exists():
|
|
220
|
+
print("๐งพ Membuat wp-config.php otomatis ...")
|
|
221
|
+
subprocess.run(
|
|
222
|
+
wp_cli_cmd + [
|
|
223
|
+
"config", "create",
|
|
224
|
+
"--dbname=" + f"{project_dir.name.lower().replace('-', '_')}_db",
|
|
225
|
+
"--dbuser=root",
|
|
226
|
+
"--dbpass=",
|
|
227
|
+
"--dbhost=localhost",
|
|
228
|
+
"--skip-check"
|
|
229
|
+
],
|
|
230
|
+
cwd=project_dir,
|
|
231
|
+
check=False
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# === Pastikan wp-config.php ada ===
|
|
235
|
+
db_name = f"{project_dir.name.lower().replace('-', '_')}_db"
|
|
236
|
+
wp_config = project_dir / "wp-config.php"
|
|
237
|
+
|
|
238
|
+
if not wp_config.exists():
|
|
239
|
+
print(f"๐งฑ Membuat wp-config.php untuk {db_name} ...")
|
|
240
|
+
|
|
241
|
+
subprocess.run([
|
|
242
|
+
wp_cli,
|
|
243
|
+
"config",
|
|
244
|
+
"create",
|
|
245
|
+
f"--dbname={db_name}",
|
|
246
|
+
"--dbuser=root",
|
|
247
|
+
"--dbpass=",
|
|
248
|
+
"--dbhost=localhost"
|
|
249
|
+
], cwd=project_dir, check=False)
|
|
250
|
+
|
|
251
|
+
if wp_config.exists():
|
|
252
|
+
print("โ
wp-config.php berhasil dibuat.")
|
|
253
|
+
else:
|
|
254
|
+
print("โ ๏ธ Gagal membuat wp-config.php, cek WP-CLI dan izin folder.")
|
|
255
|
+
|
|
256
|
+
# === Jalankan wp core install jika belum ada wp_options ===
|
|
257
|
+
print("โ๏ธ Menjalankan instalasi WordPress awal ...")
|
|
258
|
+
subprocess.run(
|
|
259
|
+
wp_cli_cmd + [
|
|
260
|
+
"core", "install",
|
|
261
|
+
"--url=http://localhost/" + project_dir.name,
|
|
262
|
+
"--title=" + project_dir.name,
|
|
263
|
+
"--admin_user=admin",
|
|
264
|
+
"--admin_password=admin",
|
|
265
|
+
"--admin_email=admin@example.com"
|
|
266
|
+
],
|
|
267
|
+
cwd=project_dir,
|
|
268
|
+
check=False
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
print("๐ Menginstal plugin dan theme sesuai devcore_project.json ...")
|
|
272
|
+
|
|
273
|
+
# Jalankan instalasi plugin
|
|
274
|
+
for plugin in plugins:
|
|
275
|
+
print(f"โก๏ธ Install plugin: {plugin}")
|
|
276
|
+
subprocess.run(wp_cli_cmd + ["plugin", "install", plugin, "--activate"], cwd=project_dir, check=False)
|
|
277
|
+
|
|
278
|
+
# Jalankan instalasi theme
|
|
279
|
+
for theme in themes:
|
|
280
|
+
print(f"๐จ Install theme: {theme}")
|
|
281
|
+
subprocess.run(wp_cli_cmd + ["theme", "install", theme, "--activate"], cwd=project_dir, check=False)
|
|
282
|
+
|
|
283
|
+
print("โ
Semua plugin dan theme selesai diinstall.")
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devcore-cli
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: DevCore โ WordPress & Laravel project automation CLI
|
|
5
|
+
Author: Puji Ermanto | <Engineer>
|
|
6
|
+
Author-email: puji@gmail.com
|
|
7
|
+
Requires-Python: >=3.8
|
|
8
|
+
Requires-Dist: jinja2>=3.1.2
|
|
9
|
+
Dynamic: author
|
|
10
|
+
Dynamic: author-email
|
|
11
|
+
Dynamic: requires-dist
|
|
12
|
+
Dynamic: requires-python
|
|
13
|
+
Dynamic: summary
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
setup.py
|
|
4
|
+
core/__init__.py
|
|
5
|
+
core/command_config.py
|
|
6
|
+
core/command_wp_setup.py
|
|
7
|
+
core/db.py
|
|
8
|
+
core/env_manager.py
|
|
9
|
+
core/github_integration.py
|
|
10
|
+
core/template_engine.py
|
|
11
|
+
core/wp_dropdb.py
|
|
12
|
+
core/wp_init.py
|
|
13
|
+
devcore_cli.egg-info/PKG-INFO
|
|
14
|
+
devcore_cli.egg-info/SOURCES.txt
|
|
15
|
+
devcore_cli.egg-info/dependency_links.txt
|
|
16
|
+
devcore_cli.egg-info/entry_points.txt
|
|
17
|
+
devcore_cli.egg-info/requires.txt
|
|
18
|
+
devcore_cli.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
jinja2>=3.1.2
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
core
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="devcore-cli",
|
|
5
|
+
version="1.0.1",
|
|
6
|
+
author="Puji Ermanto | <Engineer>",
|
|
7
|
+
author_email="puji@gmail.com",
|
|
8
|
+
description="DevCore โ WordPress & Laravel project automation CLI",
|
|
9
|
+
packages=find_packages(),
|
|
10
|
+
include_package_data=True,
|
|
11
|
+
install_requires=[
|
|
12
|
+
"jinja2>=3.1.2",
|
|
13
|
+
],
|
|
14
|
+
entry_points={
|
|
15
|
+
"console_scripts": [
|
|
16
|
+
"devcore=devcore:main",
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
python_requires=">=3.8",
|
|
20
|
+
)
|