Skip to content

Commit e6eeae8

Browse files
committed
publishing pipeline update + model spec
1 parent baf312a commit e6eeae8

26 files changed

Lines changed: 1091 additions & 430 deletions

.env.example

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Port
22
PORT=8000
33

4+
# Image
5+
CHATMOCK_IMAGE=storagetime/chatmock:latest
6+
47
# Auth dir
58
CHATGPT_LOCAL_HOME=/data
69

@@ -11,7 +14,7 @@ VERBOSE=false
1114
# CHATGPT_LOCAL_CLIENT_ID=app_EMoamEEZ73f0CkXaXp7hrann
1215

1316
# Reasoning controls
14-
CHATGPT_LOCAL_REASONING_EFFORT=medium # minimal|low|medium|high
17+
CHATGPT_LOCAL_REASONING_EFFORT=medium # none|minimal|low|medium|high|xhigh
1518
CHATGPT_LOCAL_REASONING_SUMMARY=auto # auto|concise|detailed|none
1619
CHATGPT_LOCAL_REASONING_COMPAT=think-tags # legacy|o3|think-tags|current
1720
CHATGPT_LOCAL_EXPOSE_REASONING_MODELS=false
@@ -20,4 +23,4 @@ CHATGPT_LOCAL_EXPOSE_REASONING_MODELS=false
2023
CHATGPT_LOCAL_ENABLE_WEB_SEARCH=false
2124

2225
# Force a specific model name
23-
# CHATGPT_LOCAL_DEBUG_MODEL=gpt-5
26+
# CHATGPT_LOCAL_DEBUG_MODEL=gpt-5.4

.github/workflows/ci.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
name: ci
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
with:
16+
python-version: "3.11"
17+
- uses: astral-sh/setup-uv@v5
18+
- run: uv pip install --system .
19+
- run: python -m unittest discover -s tests
20+
- run: uv build

.github/workflows/release.yml

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
name: release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*"
7+
8+
permissions:
9+
contents: write
10+
11+
jobs:
12+
validate:
13+
runs-on: ubuntu-latest
14+
outputs:
15+
version: ${{ steps.version.outputs.version }}
16+
tag: ${{ steps.version.outputs.tag }}
17+
steps:
18+
- uses: actions/checkout@v4
19+
- uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.11"
22+
- id: version
23+
run: |
24+
VERSION="${GITHUB_REF_NAME#v}"
25+
PACKAGE_VERSION="$(python - <<'PY'
26+
import runpy
27+
print(runpy.run_path("chatmock/version.py")["__version__"])
28+
PY
29+
)"
30+
if [ "$VERSION" != "$PACKAGE_VERSION" ]; then
31+
echo "Tag version $VERSION does not match package version $PACKAGE_VERSION" >&2
32+
exit 1
33+
fi
34+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
35+
echo "tag=${GITHUB_REF_NAME}" >> "$GITHUB_OUTPUT"
36+
- uses: astral-sh/setup-uv@v5
37+
- run: uv pip install --system .
38+
- run: python -m unittest discover -s tests
39+
40+
build-python:
41+
needs: validate
42+
runs-on: ubuntu-latest
43+
steps:
44+
- uses: actions/checkout@v4
45+
- uses: actions/setup-python@v5
46+
with:
47+
python-version: "3.11"
48+
- uses: astral-sh/setup-uv@v5
49+
- run: uv build
50+
- uses: actions/upload-artifact@v4
51+
with:
52+
name: python-dist
53+
path: dist/*
54+
55+
publish-pypi:
56+
needs:
57+
- validate
58+
- build-python
59+
runs-on: ubuntu-latest
60+
permissions:
61+
id-token: write
62+
steps:
63+
- uses: actions/download-artifact@v4
64+
with:
65+
name: python-dist
66+
path: dist
67+
- uses: pypa/gh-action-pypi-publish@release/v1
68+
with:
69+
packages-dir: dist
70+
71+
build-windows:
72+
needs: validate
73+
runs-on: windows-latest
74+
steps:
75+
- uses: actions/checkout@v4
76+
- uses: actions/setup-python@v5
77+
with:
78+
python-version: "3.11"
79+
- run: python -m pip install --upgrade pip
80+
- run: python -m pip install ".[gui]"
81+
- run: python build.py --name ChatMock
82+
- run: Compress-Archive -Path dist/ChatMock -DestinationPath dist/ChatMock-windows.zip
83+
shell: pwsh
84+
- uses: actions/upload-artifact@v4
85+
with:
86+
name: windows-gui
87+
path: dist/ChatMock-windows.zip
88+
89+
build-macos:
90+
needs: validate
91+
runs-on: macos-latest
92+
env:
93+
APPLE_CERTIFICATE_P12_BASE64: ${{ secrets.APPLE_CERTIFICATE_P12_BASE64 }}
94+
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
95+
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
96+
APPLE_ID: ${{ secrets.APPLE_ID }}
97+
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
98+
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
99+
steps:
100+
- uses: actions/checkout@v4
101+
- uses: actions/setup-python@v5
102+
with:
103+
python-version: "3.11"
104+
- run: python -m pip install --upgrade pip
105+
- run: python -m pip install ".[gui]"
106+
- run: |
107+
security create-keychain -p "$RUNNER_TEMP" build.keychain
108+
security default-keychain -s build.keychain
109+
security unlock-keychain -p "$RUNNER_TEMP" build.keychain
110+
security set-keychain-settings -lut 21600 build.keychain
111+
python - <<'PY'
112+
import base64
113+
import os
114+
from pathlib import Path
115+
data = os.environ["APPLE_CERTIFICATE_P12_BASE64"]
116+
Path(os.environ["RUNNER_TEMP"], "chatmock-signing.p12").write_bytes(base64.b64decode(data))
117+
PY
118+
security import "$RUNNER_TEMP/chatmock-signing.p12" -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security
119+
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$RUNNER_TEMP" build.keychain
120+
- run: python build.py --name ChatMock
121+
- run: codesign --force --deep --options runtime --sign "$APPLE_SIGNING_IDENTITY" dist/ChatMock.app
122+
- run: codesign --verify --deep --strict dist/ChatMock.app
123+
- run: python build.py --name ChatMock --dmg-only
124+
- run: codesign --force --sign "$APPLE_SIGNING_IDENTITY" dist/ChatMock.dmg
125+
- run: codesign --verify --strict dist/ChatMock.dmg
126+
- run: xcrun notarytool submit dist/ChatMock.dmg --apple-id "$APPLE_ID" --password "$APPLE_APP_SPECIFIC_PASSWORD" --team-id "$APPLE_TEAM_ID" --wait
127+
- run: xcrun stapler staple dist/ChatMock.dmg
128+
- run: xcrun stapler validate dist/ChatMock.dmg
129+
- uses: actions/upload-artifact@v4
130+
with:
131+
name: macos-gui
132+
path: dist/ChatMock.dmg
133+
134+
docker:
135+
needs: validate
136+
runs-on: ubuntu-latest
137+
steps:
138+
- uses: actions/checkout@v4
139+
- uses: docker/setup-qemu-action@v3
140+
- uses: docker/setup-buildx-action@v3
141+
- uses: docker/login-action@v3
142+
with:
143+
username: ${{ secrets.DOCKERHUB_USERNAME }}
144+
password: ${{ secrets.DOCKERHUB_TOKEN }}
145+
- id: meta
146+
uses: docker/metadata-action@v5
147+
with:
148+
images: storagetime/chatmock
149+
tags: |
150+
type=raw,value=latest
151+
type=raw,value=${{ needs.validate.outputs.tag }}
152+
type=raw,value=${{ needs.validate.outputs.version }}
153+
- uses: docker/build-push-action@v6
154+
with:
155+
context: .
156+
platforms: linux/amd64,linux/arm64
157+
push: true
158+
tags: ${{ steps.meta.outputs.tags }}
159+
labels: ${{ steps.meta.outputs.labels }}
160+
161+
homebrew:
162+
needs: validate
163+
runs-on: ubuntu-latest
164+
steps:
165+
- run: |
166+
ARCHIVE_URL="https://github.com/${GITHUB_REPOSITORY}/archive/refs/tags/${GITHUB_REF_NAME}.tar.gz"
167+
SHA256="$(curl -fsSL "$ARCHIVE_URL" | shasum -a 256 | awk '{print $1}')"
168+
git clone "https://x-access-token:${{ secrets.HOMEBREW_TAP_TOKEN }}@github.com/RayBytes/homebrew-chatmock.git" tap
169+
cd tap
170+
cat <<EOF > chatmock.rb
171+
class Chatmock < Formula
172+
include Language::Python::Virtualenv
173+
174+
desc "OpenAI & Ollama compatible API powered by your ChatGPT plan"
175+
homepage "https://github.com/RayBytes/ChatMock"
176+
url "${ARCHIVE_URL}"
177+
sha256 "${SHA256}"
178+
license "MIT"
179+
head "https://github.com/RayBytes/ChatMock.git", branch: "main"
180+
181+
depends_on "python@3.11"
182+
183+
def install
184+
virtualenv_create(libexec, "python3.11")
185+
system libexec/"bin/pip", "install", "."
186+
bin.install_symlink libexec/"bin/chatmock"
187+
end
188+
189+
def caveats
190+
<<~EOS
191+
To get started with ChatMock:
192+
chatmock login
193+
chatmock serve
194+
EOS
195+
end
196+
197+
test do
198+
output = shell_output("#{bin}/chatmock --help 2>&1")
199+
assert_match "ChatMock", output
200+
end
201+
end
202+
EOF
203+
git config user.name "github-actions[bot]"
204+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
205+
git add chatmock.rb
206+
git commit -m "chatmock ${GITHUB_REF_NAME}" || exit 0
207+
git push
208+
209+
release-assets:
210+
needs:
211+
- validate
212+
- build-python
213+
- build-windows
214+
- build-macos
215+
- publish-pypi
216+
- docker
217+
- homebrew
218+
runs-on: ubuntu-latest
219+
steps:
220+
- uses: actions/download-artifact@v4
221+
with:
222+
path: release-artifacts
223+
- run: find release-artifacts -type f | sort
224+
- uses: softprops/action-gh-release@v2
225+
with:
226+
files: |
227+
release-artifacts/python-dist/*
228+
release-artifacts/windows-gui/*
229+
release-artifacts/macos-gui/*

DOCKER.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,27 @@
44
1) Setup env:
55
cp .env.example .env
66

7-
2) Build the image:
8-
docker compose build
9-
10-
3) Login:
7+
2) Login:
118
docker compose run --rm --service-ports chatmock-login login
9+
1210
- The command prints an auth URL, copy paste it into your browser.
1311
- If your browser cannot reach the container's localhost callback, copy the full redirect URL from the browser address bar and paste it back into the terminal when prompted.
1412
- Server should stop automatically once it receives the tokens and they are saved.
1513

16-
4) Start the server:
14+
3) Start the server:
1715
docker compose up -d chatmock
1816

19-
5) Free to use it in whichever chat app you like!
17+
4) Free to use it in whichever chat app you like!
2018

2119
## Configuration
2220
Set options in `.env` or pass environment variables:
2321
- `PORT`: Container listening port (default 8000)
22+
- `CHATMOCK_IMAGE`: image tag to run (default `storagetime/chatmock:latest`)
2423
- `VERBOSE`: `true|false` to enable request/stream logs
2524
- `CHATGPT_LOCAL_REASONING_EFFORT`: minimal|low|medium|high|xhigh
2625
- `CHATGPT_LOCAL_REASONING_SUMMARY`: auto|concise|detailed|none
2726
- `CHATGPT_LOCAL_REASONING_COMPAT`: legacy|o3|think-tags|current
28-
- `CHATGPT_LOCAL_DEBUG_MODEL`: force model override (e.g., `gpt-5`)
27+
- `CHATGPT_LOCAL_DEBUG_MODEL`: force model override (e.g., `gpt-5.4`)
2928
- `CHATGPT_LOCAL_CLIENT_ID`: OAuth client id override (rarely needed)
3029
- `CHATGPT_LOCAL_EXPOSE_REASONING_MODELS`: `true|false` to add reasoning model variants to `/v1/models`
3130
- `CHATGPT_LOCAL_ENABLE_WEB_SEARCH`: `true|false` to enable default web search tool

Dockerfile

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ ENV PYTHONDONTWRITEBYTECODE=1 \
55

66
WORKDIR /app
77

8-
COPY requirements.txt ./
9-
RUN pip install --no-cache-dir -r requirements.txt
10-
11-
COPY . /app
8+
COPY pyproject.toml README.md chatmock.py prompt.md prompt_gpt5_codex.md /app/
9+
COPY chatmock /app/chatmock
10+
RUN pip install --no-cache-dir .
1211

1312
RUN mkdir -p /data
1413

@@ -19,4 +18,3 @@ EXPOSE 8000 1455
1918

2019
ENTRYPOINT ["/entrypoint.sh"]
2120
CMD ["serve"]
22-

Formula/chatmock.rb

Lines changed: 0 additions & 55 deletions
This file was deleted.

0 commit comments

Comments
 (0)