Skip to content

Commit 16a16c9

Browse files
committed
build script
1 parent dfda85d commit 16a16c9

File tree

8 files changed

+691
-796
lines changed

8 files changed

+691
-796
lines changed

build.py

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
# !/usr/bin/env python3.10
2+
3+
import os
4+
import platform
5+
import subprocess
6+
import shutil
7+
# import sys
8+
# import venv
9+
import argparse
10+
11+
12+
def parse_arguments():
13+
parser = argparse.ArgumentParser(description="Build script for AgentPilot")
14+
parser.add_argument('--skip-venv', action='store_true', help='Skip creating a new virtual environment')
15+
parser.add_argument('--version', type=str, default='0.3.1', help='Version number for the build')
16+
return parser.parse_args()
17+
18+
19+
# def get_pyenv_path():
20+
# return os.path.join(os.environ["PYENV_ROOT"], "versions", 'apbuildvenv')
21+
22+
23+
def run_command(command, shell=False, env=None):
24+
if isinstance(command, str):
25+
command = command.split()
26+
print(f"Running command: {' '.join(command)}")
27+
if env:
28+
print(f"Environment: {env}")
29+
30+
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=shell, env=env)
31+
output, error = process.communicate()
32+
if process.returncode != 0:
33+
print(f"Error executing command: {' '.join(command)}")
34+
print(f"Output: {output.decode()}")
35+
print(f"Error: {error.decode()}")
36+
exit(1)
37+
return output.decode()
38+
39+
40+
class Builder:
41+
def __init__(self):
42+
self.args = parse_arguments()
43+
self.platform = platform.system()
44+
self.version = self.args.version
45+
self.venv_path = os.path.join(os.environ["PYENV_ROOT"], "versions", 'apbuildvenv')
46+
self.pip_path = self.get_pip_path()
47+
self.pyinstaller_path = self.get_pyinstaller_path()
48+
os.chdir(os.path.dirname(os.path.abspath(__file__)))
49+
50+
def get_pip_path(self):
51+
if self.platform == "Windows":
52+
return os.path.join(self.venv_path, "Scripts", "pip")
53+
else:
54+
return os.path.join(self.venv_path, "bin", "pip")
55+
56+
def get_pyinstaller_path(self):
57+
if self.platform == "Windows":
58+
return os.path.join(self.venv_path, "Scripts", "pyinstaller.exe")
59+
else:
60+
return os.path.join(self.venv_path, "bin", "pyinstaller")
61+
62+
def create_executable(self):
63+
self.setup_environment()
64+
self.install_requirements()
65+
self.build_project()
66+
self.copy_assets()
67+
68+
if self.platform == "Windows":
69+
self.rename_executable()
70+
elif self.platform == "Linux":
71+
self.make_appimage()
72+
73+
self.move_all_to_folder()
74+
self.compress_app()
75+
76+
def setup_environment(self):
77+
if self.args.skip_venv:
78+
return
79+
80+
output = run_command("pyenv virtualenvs --bare")
81+
venvs = output.splitlines()
82+
env_exists = 'apbuildvenv' in venvs
83+
if env_exists:
84+
run_command("pyenv virtualenv-delete -f apbuildvenv")
85+
86+
print("Creating new pyenv virtual environment..")
87+
run_command("pyenv virtualenv 3.10.11 apbuildvenv")
88+
89+
def install_requirements(self):
90+
run_command([self.pip_path, "install", "-r", "requirements.txt"])
91+
92+
def build_project(self):
93+
print("Installing PyInstaller..")
94+
run_command([self.pip_path, "install", "pyinstaller"])
95+
96+
print("Building executable..")
97+
run_command([self.pyinstaller_path, "build.spec"])
98+
99+
def copy_assets(self):
100+
shutil.copy("data.db", "dist/data.db")
101+
shutil.copytree("docs/avatars", "dist/avatars", dirs_exist_ok=True)
102+
103+
def rename_executable(self):
104+
old_filename = "__main__"
105+
new_filename = f"AgentPilot_{self.version}"
106+
if self.platform == "Windows":
107+
os.rename(f"dist/{old_filename}.exe", f"dist/{new_filename}.exe")
108+
else:
109+
os.rename(f"dist/{old_filename}", f"dist/{new_filename}")
110+
111+
def move_all_to_folder(self):
112+
folder_name = f"AgentPilot_{self.version}_{self.platform}_Portable"
113+
114+
if os.path.exists(f'dist/{folder_name}'):
115+
shutil.rmtree(f'dist/{folder_name}')
116+
os.mkdir(f'dist/{folder_name}')
117+
118+
# move all files to folder
119+
ignore_exts = ['zip', 'tar.gz']
120+
for file in os.listdir("dist"):
121+
if file != folder_name and not any(file.endswith(e) for e in ignore_exts):
122+
shutil.move(f"dist/{file}", f"dist/{folder_name}/{file}")
123+
124+
def make_appimage(self):
125+
# Create AppDir folder
126+
if os.path.exists("AppDir"):
127+
shutil.rmtree("AppDir")
128+
os.mkdir("AppDir")
129+
130+
# make AppDir/usr/bin
131+
os.makedirs("AppDir/usr/bin")
132+
133+
# create agentpilot.desktop
134+
with open("AppDir/agentpilot.desktop", "w") as f:
135+
f.write("""[Desktop Entry]
136+
Type=Application
137+
Name=AgentPilot
138+
Comment=Build and chat with agents
139+
Exec=usr/bin/main
140+
Icon=icon
141+
Terminal=false
142+
Categories=Utility;""")
143+
144+
# create AppRun link
145+
with open("AppDir/AppRun", "w") as f:
146+
f.write('''#!/bin/sh
147+
HERE=$(dirname "$(readlink -f "${0}")")
148+
export PATH="${HERE}/usr/bin:$PATH"
149+
exec main "$@"''')
150+
os.chmod("AppDir/AppRun", 0o755)
151+
152+
# copy icon
153+
shutil.copy("src/utils/resources/icon.png", "AppDir/icon.png")
154+
shutil.copy("src/utils/resources/icon.png", "AppDir/.DirIcon")
155+
156+
# copy executable
157+
shutil.copy(f"dist/__main__", "AppDir/usr/bin/main")
158+
159+
# check if appimagetool file exists
160+
if not os.path.exists("appimagetool.AppImage"):
161+
print("AppImageTool not found. Downloading..")
162+
run_command("wget -c https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage")
163+
os.rename("appimagetool-x86_64.AppImage", "appimagetool.AppImage")
164+
165+
# make appimage with appimagetool
166+
run_command("chmod +x appimagetool.AppImage")
167+
run_command("./appimagetool.AppImage AppDir")
168+
169+
# rename appimage and move to the folder
170+
os.rename("AgentPilot-x86_64.AppImage", f"dist/AgentPilot_{self.version}.AppImage")
171+
172+
# remove the original executable
173+
os.remove(f"dist/__main__")
174+
175+
def compress_app(self):
176+
source_folder = f"dist/AgentPilot_{self.version}_{self.platform}_Portable"
177+
output_filename = f"dist/AgentPilot_{self.version}_{self.platform}_Portable"
178+
179+
base_name = os.path.basename(source_folder)
180+
base_dir = os.path.dirname(source_folder)
181+
182+
ext = "zip" if self.platform == "Windows" else "tar.gz"
183+
if os.path.exists(f"{output_filename}.{ext}"):
184+
os.remove(f"{output_filename}.{ext}")
185+
186+
if self.platform == "Windows":
187+
shutil.make_archive(
188+
base_name=output_filename,
189+
format="zip",
190+
root_dir=base_dir,
191+
base_dir=base_name
192+
)
193+
else:
194+
shutil.make_archive(
195+
base_name=output_filename,
196+
format="gztar",
197+
root_dir=base_dir,
198+
base_dir=base_name
199+
)
200+
201+
202+
if __name__ == "__main__":
203+
builder = Builder()
204+
builder.create_executable()

0 commit comments

Comments
 (0)