Skip to content

Commit aadb326

Browse files
authored
build: added pyinstaller build script for gptme-server (gptme#539)
* build: added pyinstaller build script for gptme-server * ci: added build-pyinstaller job * ci: disable windows for the build-pyinstaller job, for now * build: moved gptme-server.spec into scripts/pyinstaller/, misc fixes * ci: split up build workflow into build, test, and lint workflows * docs: renamed file
1 parent ae3d285 commit aadb326

File tree

10 files changed

+472
-119
lines changed

10 files changed

+472
-119
lines changed

.github/workflows/build.yml

Lines changed: 29 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -8,100 +8,9 @@ on:
88
pull_request:
99
branches: [ master ]
1010

11-
env:
12-
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
13-
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
14-
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
15-
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
16-
1711
jobs:
18-
build:
19-
name: Test ${{ matrix.os }} with `${{ matrix.extras }}` on ${{ matrix.model }}
20-
runs-on: ${{ matrix.os }}
21-
env:
22-
RELEASE: false
23-
strategy:
24-
fail-fast: false
25-
matrix:
26-
os: [ubuntu-latest]
27-
python_version: ['3.10']
28-
extras: ['-E all']
29-
model: ['openai/gpt-4o-mini', 'anthropic/claude-3-haiku-20240307']
30-
#include:
31-
# deepseek, no extras, latest python
32-
#- os: ubuntu-latest
33-
# python_version: '3.13'
34-
# extras: ''
35-
# model: 'deepseek/deepseek-chat'
36-
# openrouter
37-
#- os: ubuntu-latest
38-
# python_version: '3.10'
39-
# extras: ''
40-
# model: 'openrouter/deepseek/deepseek-chat'
41-
# openrouter (llama)
42-
#- os: ubuntu-latest
43-
# python_version: '3.10'
44-
# extras: ''
45-
# model: 'openrouter/meta-llama/llama-3.3-70B-instruct'
46-
47-
steps:
48-
- uses: actions/checkout@v4
49-
with:
50-
submodules: 'recursive'
51-
- name: Install apt dependencies
52-
run: sudo apt-get install universal-ctags pandoc tmux x11-xserver-utils xvfb
53-
54-
- name: Set up Xvfb
55-
run: |
56-
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
57-
echo "DISPLAY=:99" >> $GITHUB_ENV
58-
59-
- name: Install poetry
60-
run: pipx install poetry
61-
62-
- name: Set up Python
63-
uses: actions/setup-python@v5
64-
with:
65-
python-version: ${{ matrix.python_version }}
66-
cache: 'poetry'
67-
68-
- name: Install dependencies
69-
run: |
70-
make build
71-
poetry install ${{ matrix.extras }}
72-
73-
- name: Install playwright
74-
if: contains(matrix.extras, 'browser') || contains(matrix.extras, 'all')
75-
run: poetry run playwright install chromium
76-
77-
# old comment: OpenAI sometimes randomly aborts connections
78-
- name: Run tests
79-
uses: nick-fields/retry@v3
80-
env:
81-
TERM: xterm
82-
MODEL: ${{ matrix.model }}
83-
with:
84-
timeout_minutes: 5
85-
max_attempts: 1 # favor pytest retries (mark with flaky)
86-
retry_wait_seconds: 10
87-
command: make test SLOW=true
88-
89-
- name: Upload coverage reports to Codecov
90-
uses: codecov/codecov-action@v5
91-
env:
92-
MODEL: ${{ matrix.model }}
93-
with:
94-
token: ${{ secrets.CODECOV_TOKEN }}
95-
env_vars: MODEL
96-
flags: ${{ matrix.model }}
97-
98-
- name: Upload test results to Codecov
99-
if: ${{ !cancelled() }}
100-
uses: codecov/test-results-action@v1
101-
with:
102-
token: ${{ secrets.CODECOV_TOKEN }}
103-
10412
build-docker:
13+
name: Docker
10514
runs-on: ubuntu-latest
10615
env:
10716
SHOULD_PUSH: ${{ github.ref == 'refs/tags/v*' || github.ref == 'refs/heads/master' }}
@@ -190,41 +99,44 @@ jobs:
19099
# RUST=yes
191100
# BROWSER=yes
192101

193-
lint:
194-
runs-on: ubuntu-latest
195-
steps:
196-
- uses: actions/checkout@v4
197-
- name: Install poetry
198-
run: pipx install poetry
199-
- name: Set up Python
200-
uses: actions/setup-python@v5
201-
with:
202-
python-version: '3.10'
203-
cache: 'poetry'
204-
- name: Install dependencies
205-
run: |
206-
make build
207-
poetry install
208-
- name: Check for lint
209-
run: |
210-
make lint
102+
build-pyinstaller:
103+
name: PyInstaller binaries on ${{ matrix.os }}
104+
runs-on: ${{ matrix.os }}
105+
strategy:
106+
fail-fast: false
107+
matrix:
108+
os: [ubuntu-latest, macos-latest] # windows-latest
109+
python_version: ['3.10']
211110

212-
typecheck:
213-
runs-on: ubuntu-latest
214111
steps:
215112
- uses: actions/checkout@v4
216113
- name: Install poetry
217114
run: pipx install poetry
218115
- name: Set up Python
219116
uses: actions/setup-python@v5
220117
with:
221-
python-version: '3.10'
118+
python-version: ${{ matrix.python_version }}
222119
cache: 'poetry'
223120
- name: Install dependencies
224121
run: |
225122
make build
226-
poetry install -E server -E browser
227-
poetry run pip install tomli tomli_w
228-
- name: Typecheck
123+
poetry install --extras server --with dev
124+
- name: Build PyInstaller executable
125+
run: make build-server-exe
126+
- name: Test executable (Unix)
127+
if: runner.os != 'Windows'
128+
run: |
129+
./dist/gptme-server --help
130+
echo "✅ gptme-server --help executed successfully"
131+
- name: Test executable (Windows)
132+
if: runner.os == 'Windows'
229133
run: |
230-
make typecheck
134+
.\dist\gptme-server.exe --help
135+
echo "✅ gptme-server.exe --help executed successfully"
136+
- name: Upload executable artifact
137+
uses: actions/upload-artifact@v4
138+
with:
139+
name: gptme-server-${{ matrix.os }}
140+
path: |
141+
dist/gptme-server*
142+
retention-days: 7

.github/workflows/lint.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- name: Install poetry
15+
run: pipx install poetry
16+
- name: Set up Python
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: '3.10'
20+
cache: 'poetry'
21+
- name: Install dependencies
22+
run: |
23+
make build
24+
poetry install
25+
- name: Check for lint
26+
run: |
27+
make lint
28+
29+
typecheck:
30+
runs-on: ubuntu-latest
31+
steps:
32+
- uses: actions/checkout@v4
33+
- name: Install poetry
34+
run: pipx install poetry
35+
- name: Set up Python
36+
uses: actions/setup-python@v5
37+
with:
38+
python-version: '3.10'
39+
cache: 'poetry'
40+
- name: Install dependencies
41+
run: |
42+
make build
43+
poetry install -E server -E browser
44+
poetry run pip install tomli tomli_w
45+
- name: Typecheck
46+
run: |
47+
make typecheck

.github/workflows/test.yml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Test
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
env:
10+
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
11+
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
12+
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
13+
OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
14+
15+
jobs:
16+
test:
17+
name: Test with `${{ matrix.extras }}` and ${{ matrix.model }} on ${{ matrix.os }}
18+
runs-on: ${{ matrix.os }}
19+
env:
20+
RELEASE: false
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
os: [ubuntu-latest]
25+
python_version: ['3.10']
26+
extras: ['-E all']
27+
model: ['openai/gpt-4o-mini', 'anthropic/claude-3-haiku-20240307']
28+
#include:
29+
# deepseek, no extras, latest python
30+
#- os: ubuntu-latest
31+
# python_version: '3.13'
32+
# extras: ''
33+
# model: 'deepseek/deepseek-chat'
34+
# openrouter
35+
#- os: ubuntu-latest
36+
# python_version: '3.10'
37+
# extras: ''
38+
# model: 'openrouter/deepseek/deepseek-chat'
39+
# openrouter (llama)
40+
#- os: ubuntu-latest
41+
# python_version: '3.10'
42+
# extras: ''
43+
# model: 'openrouter/meta-llama/llama-3.3-70B-instruct'
44+
45+
steps:
46+
- uses: actions/checkout@v4
47+
with:
48+
submodules: 'recursive'
49+
- name: Install apt dependencies
50+
run: sudo apt-get install universal-ctags pandoc tmux x11-xserver-utils xvfb
51+
52+
- name: Set up Xvfb
53+
run: |
54+
Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
55+
echo "DISPLAY=:99" >> $GITHUB_ENV
56+
57+
- name: Install poetry
58+
run: pipx install poetry
59+
60+
- name: Set up Python
61+
uses: actions/setup-python@v5
62+
with:
63+
python-version: ${{ matrix.python_version }}
64+
cache: 'poetry'
65+
66+
- name: Install dependencies
67+
run: |
68+
make build
69+
poetry install ${{ matrix.extras }}
70+
71+
- name: Install playwright
72+
if: contains(matrix.extras, 'browser') || contains(matrix.extras, 'all')
73+
run: poetry run playwright install chromium
74+
75+
# old comment: OpenAI sometimes randomly aborts connections
76+
- name: Run tests
77+
uses: nick-fields/retry@v3
78+
env:
79+
TERM: xterm
80+
MODEL: ${{ matrix.model }}
81+
with:
82+
timeout_minutes: 5
83+
max_attempts: 1 # favor pytest retries (mark with flaky)
84+
retry_wait_seconds: 10
85+
command: make test SLOW=true
86+
87+
- name: Upload coverage reports to Codecov
88+
uses: codecov/codecov-action@v5
89+
env:
90+
MODEL: ${{ matrix.model }}
91+
with:
92+
token: ${{ secrets.CODECOV_TOKEN }}
93+
env_vars: MODEL
94+
flags: ${{ matrix.model }}
95+
96+
- name: Upload test results to Codecov
97+
if: ${{ !cancelled() }}
98+
uses: codecov/test-results-action@v1
99+
with:
100+
token: ${{ secrets.CODECOV_TOKEN }}

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ build-docker-full:
4040
docker build . -t gptme:latest -f scripts/Dockerfile
4141
docker build . -t gptme-eval:latest -f scripts/Dockerfile.eval --build-arg RUST=yes --build-arg PLAYWRIGHT=no
4242

43+
build-server-exe: ## Build gptme-server executable with PyInstaller
44+
./scripts/build_server_executable.sh
45+
4346
test:
4447
@# if SLOW is not set, pass `-m "not slow"` to skip slow tests
4548
poetry run pytest ${SRCDIRS} -v --log-level INFO --durations=5 \
@@ -138,7 +141,7 @@ release: version dist/CHANGELOG.md
138141
git push origin master $${VERSION} && \
139142
gh release create $${VERSION} -t $${VERSION} -F dist/CHANGELOG.md
140143

141-
clean: clean-docs clean-site clean-test
144+
clean: clean-docs clean-site clean-test clean-build
142145

143146
clean-site:
144147
rm -rf site/dist
@@ -151,6 +154,9 @@ clean-test:
151154
rm -I $$HOME/.local/share/gptme/logs/*test-*-test_*/*.jsonl || true
152155
rm --dir $$HOME/.local/share/gptme/logs/*test-*-test_*/ || true
153156

157+
clean-build: ## Clean PyInstaller build artifacts
158+
rm -rf build/ dist/ *.spec.bak
159+
154160
rename-logs:
155161
./scripts/auto_rename_logs.py $(if $(APPLY),--no-dry-run) --limit $(or $(LIMIT),10)
156162

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ You can find more [Demos][docs-demos] and [Examples][docs-examples] in the [docu
206206
- Modern web interface at [chat.gptme.org](https://chat.gptme.org) ([gptme-webui])
207207
- Simple built-in web UI included in the Python package
208208
- [Server][docs-server] with REST API
209+
- Standalone executable builds available with PyInstaller
209210
- 💻 [Computer use][docs-tools-computer] tool, as hyped by [Anthropic][anthropic-computer-use] (see [#216](https://github.com/gptme/gptme/issues/216))
210211
- Give the assistant access to a full desktop, allowing it to interact with GUI applications.
211212
- 🤖 Long-running agents and advanced agent architectures (see [#143](https://github.com/gptme/gptme/issues/143) and [#259](https://github.com/gptme/gptme/issues/259))

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ See the `README <https://github.com/gptme/gptme/blob/master/README.md>`_ file fo
3434
:caption: Developer Guide
3535

3636
contributing
37+
building
3738
prompts
3839
evals
3940
bot

0 commit comments

Comments
 (0)