-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathbuild.py
More file actions
153 lines (122 loc) · 4.93 KB
/
build.py
File metadata and controls
153 lines (122 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import os
import shutil
import subprocess
import sys
import glob
import time
import stat
def handle_remove_readonly(func, path, exc):
import stat
excvalue = exc[1]
if excvalue.errno == 5: # Access Denied
os.chmod(path, stat.S_IWRITE)
try:
func(path)
except Exception:
# If it still fails, it might be a process lock or a nested issue
pass
else:
raise
def archive_old_builds():
releases_dir = "releases"
archive_dir = os.path.join(releases_dir, "archive")
if not os.path.exists(archive_dir):
os.makedirs(archive_dir, exist_ok=True)
print(f"Created archive directory: {archive_dir}")
# Also check root for any stray zips to migrate them
for file_path in glob.glob("DarkMatterBot_v*.zip"):
try:
timestamp = time.strftime("%Y%m%d_%H%M%S")
filename = os.path.basename(file_path)
name, ext = os.path.splitext(filename)
new_name = f"{name}_{timestamp}{ext}"
destination = os.path.join(archive_dir, new_name)
shutil.move(file_path, destination)
print(f"Migrated and archived: {file_path} -> {destination}")
except Exception as e:
print(f"Failed to archive {file_path}: {e}")
# Archive any previous zips already in releases (but not in archive subfolder)
for file_path in glob.glob(os.path.join(releases_dir, "DarkMatterBot_v*.zip")):
try:
timestamp = time.strftime("%Y%m%d_%H%M%S")
filename = os.path.basename(file_path)
name, ext = os.path.splitext(filename)
new_name = f"{name}_{timestamp}{ext}"
destination = os.path.join(archive_dir, new_name)
shutil.move(file_path, destination)
print(f"Archived previous release: {file_path} -> {destination}")
except Exception as e:
print(f"Failed to archive {file_path}: {e}")
def install_pyinstaller():
try:
import PyInstaller
print("PyInstaller is already installed.")
except ImportError:
print("Installing PyInstaller...")
subprocess.check_call([sys.executable, "-m", "pip", "install", "pyinstaller"])
def build_executable():
print("Archiving old builds...")
archive_old_builds()
print("Cleaning up previous builds...")
if os.path.exists("build"):
shutil.rmtree("build", ignore_errors=False, onerror=handle_remove_readonly)
if os.path.exists("dist"):
shutil.rmtree("dist", ignore_errors=False, onerror=handle_remove_readonly)
print("Building executable...")
# Define the PyInstaller command
# --noconfirm: overwrite output directory
# --onefile: package into a single exe
# --windowed: no console window
# --icon: set the application icon
# --add-data: include the resources directory
# --name: name of the executable
sep = ";" if os.name == "nt" else ":"
command = [
"pyinstaller",
"--noconfirm",
"--onefile", # Package into a single exe
"--windowed",
"--icon=resources/favicon.ico",
f"--add-data=resources{sep}resources",
f"--add-data=ui{sep}ui",
"--hidden-import=customtkinter",
"--hidden-import=curl_cffi",
"--name=DarkMatterBot",
"main.py",
]
try:
subprocess.check_call(command)
print("\nBuild successful! Executable is in the 'dist' directory.")
# Create a zip file for distribution
print("Creating distribution archive...")
import zipfile
releases_dir = "releases"
if not os.path.exists(releases_dir):
os.makedirs(releases_dir)
zip_name = "DarkMatterBot_v3.6.0.zip"
zip_path = os.path.join(releases_dir, zip_name)
with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
zipf.write("dist/DarkMatterBot.exe", "DarkMatterBot.exe")
print(f"Archive created: {zip_path}")
except subprocess.CalledProcessError as e:
print(f"\nBuild failed: {e}")
if __name__ == "__main__":
# Ensure we are running in the venv
venv_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".venv")
if os.path.exists(venv_path):
# Check if sys.executable is inside the venv
if not sys.executable.startswith(os.path.abspath(venv_path)):
print("Not running in venv. Relaunching via venv...")
if os.name == "nt":
python_executable = os.path.join(venv_path, "Scripts", "python.exe")
else:
python_executable = os.path.join(venv_path, "bin", "python")
if os.path.exists(python_executable):
subprocess.check_call([python_executable] + sys.argv)
sys.exit(0)
else:
print(
"Warning: .venv found but python executable not found. Continuing..."
)
install_pyinstaller()
build_executable()