Skip to content

fix: make seed script standalone, no app module imports #28

fix: make seed script standalone, no app module imports

fix: make seed script standalone, no app module imports #28

Workflow file for this run

name: Desktop Release
on:
push:
tags:
- 'desktop-v*'
workflow_dispatch:
permissions:
contents: write
jobs:
create-release:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/desktop-v')
steps:
- uses: actions/checkout@v4
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release create "${{ github.ref_name }}" \
--title "QueryGPT Desktop ${{ github.ref_name }}" \
--draft \
--notes "$(cat <<'NOTES'
## Downloads
| Platform | File |
|----------|------|
| macOS (Apple Silicon) | `.dmg` or `.zip` |
| macOS (Intel) | `.dmg` or `.zip` |
| Windows | `.exe` installer |
## Install
### macOS
1. Download and open the `.dmg`, drag QueryGPT to Applications
2. First launch will show "app is damaged" — run this in Terminal:
```
xattr -cr /Applications/QueryGPT.app
```
3. Open QueryGPT from Applications
> This happens because the app is not code-signed yet.
### Windows
Run the `.exe` installer and follow the prompts.
## Features
- Natural language to SQL with any OpenAI-compatible model
- Database connections: PostgreSQL, MySQL, SQLite
- Semantic layer for custom business metrics
- Query history and result visualization
- i18n support (English / 中文)
NOTES
)"
build:
needs: create-release
if: always()
strategy:
fail-fast: false
matrix:
include:
- os: macos-14
platform: mac
arch: arm64
electron_args: --mac --arm64
- os: macos-14
platform: mac
arch: x64
electron_args: --mac --x64
- os: windows-latest
platform: win
arch: x64
electron_args: --win --x64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install web dependencies
run: cd apps/web && npm ci
- name: Install desktop dependencies
run: cd apps/desktop && npm ci
# API venv for `uv pip freeze` in build script
- name: Setup API venv
shell: bash
run: |
cd apps/api
python -m venv .venv
if [ "$RUNNER_OS" = "Windows" ]; then
.venv/Scripts/pip install -e "."
else
.venv/bin/pip install -e "."
fi
- name: Build backend
run: cd apps/desktop && npx tsx scripts/build-pyinstaller.ts
shell: bash
- name: Build frontend
run: cd apps/desktop && npx tsx scripts/build-next.ts
shell: bash
- name: Compile TypeScript
run: cd apps/desktop && npx tsc -p tsconfig.electron.json
- name: Package
env:
CSC_IDENTITY_AUTO_DISCOVERY: 'false'
run: cd apps/desktop && npx electron-builder ${{ matrix.electron_args }} --publish never --config electron-builder.yml
shell: bash
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: desktop-${{ matrix.platform }}-${{ matrix.arch }}
path: |
apps/desktop/release/*.dmg
apps/desktop/release/*.zip
apps/desktop/release/*.exe
if-no-files-found: error
retention-days: 7
# Upload directly to release via GitHub API (gh CLI truncates large files)
- name: Upload to release
if: startsWith(github.ref, 'refs/tags/desktop-v')
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Get release ID (draft releases are not queryable by tag, use list API)
RELEASE_ID=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/releases" \
| jq -r '.[] | select(.tag_name == "${{ github.ref_name }}") | .id' | head -1)
echo "Release ID: $RELEASE_ID"
for file in apps/desktop/release/*.dmg apps/desktop/release/*.zip apps/desktop/release/*.exe; do
[ -f "$file" ] || continue
filename=$(basename "$file")
filesize=$(wc -c < "$file" | tr -d ' ')
echo "Uploading $filename ($filesize bytes)..."
# Delete existing asset if any
existing=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets" \
| jq -r ".[] | select(.name == \"$filename\") | .id")
if [ -n "$existing" ]; then
curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/releases/assets/$existing"
echo " Deleted existing asset"
fi
for attempt in 1 2 3; do
# Use --upload-file which is designed for reliable binary uploads
response=$(curl -s -w "\n%{http_code}" \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Content-Type: application/octet-stream" \
--upload-file "$file" \
"https://uploads.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets?name=$filename")
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
uploaded_size=$(echo "$body" | jq -r '.size // 0')
if [ "$http_code" = "201" ] && [ "$uploaded_size" = "$filesize" ]; then
echo " OK (verified: $uploaded_size bytes)"
break
fi
echo " Attempt $attempt: HTTP $http_code, uploaded=$uploaded_size expected=$filesize"
# Clean up partial upload
new_asset=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/releases/$RELEASE_ID/assets" \
| jq -r ".[] | select(.name == \"$filename\") | .id")
[ -n "$new_asset" ] && curl -s -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/${{ github.repository }}/releases/assets/$new_asset"
sleep 10
done
done