Skip to content

Murder the twins: add_model_menu and model_settings_menu on termflow #1141

Murder the twins: add_model_menu and model_settings_menu on termflow

Murder the twins: add_model_menu and model_settings_menu on termflow #1141

Workflow file for this run

# Publishes your package to PyPI using Astral/uv for builds.
# Set PYPI_API_TOKEN in repo secrets.
permissions:
contents: write # Allows writing to the repository
name: Build and Publish to PyPI
on:
push:
branches:
- main
# Serialize publishes: two back-to-back pushes once raced, both bumped to the
# same patch version, and the loser stranded git a version behind PyPI.
# Queue (never cancel) so every push still gets released, one at a time.
concurrency:
group: pypi-publish
cancel-in-progress: false
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [macos-latest]
python-version: ['3.13']
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
run: pip install uv
- name: Setup uv virtual environment
run: uv venv
- name: Install dependencies
# [durable] extras pulls in dbos, required by integration test
# tests/integration/test_dbos_enabled.py
run: uv pip install -e ".[durable]"
- name: Install pexpect for integration tests
run: uv pip install pexpect>=4.9.0
- name: Provision CI model (lilac synthetic GLM-5.2)
# models.json ships empty. CI gets its model from extra_models.json,
# exactly like a real user would after running /add_model.
run: |
mkdir -p "$HOME/.code_puppy"
cat > "$HOME/.code_puppy/extra_models.json" <<'JSON'
{
"lilac-zai-org-glm-5.2": {
"type": "custom_openai",
"provider": "lilac",
"name": "zai-org/glm-5.2",
"custom_endpoint": {
"url": "https://api.getlilac.com/v1",
"api_key": "$LILAC_API_KEY"
},
"context_length": 524288,
"supported_settings": ["temperature", "seed", "top_p"]
}
}
JSON
# Tests isolate user config, and several fallback contracts require a
# non-empty bundled catalog. Keep this test-only copy out of releases:
# the publish job starts from a fresh checkout.
cp "$HOME/.code_puppy/extra_models.json" code_puppy/models.json
echo "Wrote CI model catalog and test-only bundled fallback"
- name: Debug environment variables
env:
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY || 'fake-key-for-ci-testing' }}
CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY || 'fake-key-for-ci-testing' }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY || 'fake-key-for-ci-testing' }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY || 'fake-key-for-ci-testing' }}
SYN_API_KEY: ${{ secrets.SYN_API_KEY || 'fake-key-for-ci-testing' }}
LILAC_API_KEY: ${{ secrets.LILAC_API_KEY || 'fake-key-for-ci-testing' }}
run: |
echo "=== DEBUG: Environment Variables ==="
echo "CEREBRAS_API_KEY is set: ${{ secrets.CEREBRAS_API_KEY != '' }}"
echo "CONTEXT7_API_KEY is set: ${{ secrets.CONTEXT7_API_KEY != '' }}"
echo "OPENAI_API_KEY is set: ${{ secrets.OPENAI_API_KEY != '' }}"
echo "ANTHROPIC_API_KEY is set: ${{ secrets.ANTHROPIC_API_KEY != '' }}"
echo "SYN_API_KEY is set: ${{ secrets.SYN_API_KEY != '' }}"
echo "CEREBRAS_API_KEY length: ${#CEREBRAS_API_KEY}"
echo "CONTEXT7_API_KEY length: ${#CONTEXT7_API_KEY}"
echo "OPENAI_API_KEY length: ${#OPENAI_API_KEY}"
echo "ANTHROPIC_API_KEY length: ${#ANTHROPIC_API_KEY}"
echo "SYN_API_KEY length: ${#SYN_API_KEY}"
echo "=== END DEBUG ==="
- name: Run tests
env:
CI: '1'
CODE_PUPPY_TEST_FAST: '1'
CEREBRAS_API_KEY: ${{ secrets.CEREBRAS_API_KEY || 'fake-key-for-ci-testing' }}
CONTEXT7_API_KEY: ${{ secrets.CONTEXT7_API_KEY || 'fake-key-for-ci-testing' }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY || 'fake-key-for-ci-testing' }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY || 'fake-key-for-ci-testing' }}
SYN_API_KEY: ${{ secrets.SYN_API_KEY || 'fake-key-for-ci-testing' }}
LILAC_API_KEY: ${{ secrets.LILAC_API_KEY || 'fake-key-for-ci-testing' }}
run: |
echo "Running tests (including integration tests) on ${{ runner.os }} with Python ${{ matrix.python-version }}..."
echo "Required environment variables are set (using CI fallbacks if secrets not available)"
uv run pytest tests/ -v --cov=code_puppy --cov-report=term-missing
build-publish:
runs-on: ubuntu-latest
needs: test
permissions:
contents: write # Allows writing to the repository
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Python 3.13
uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Install uv, build, and twine
run: pip install uv build twine
- name: Setup uv virtual environment
run: uv venv
- name: Bump version
run: uv version --bump patch
- name: Capture new version
id: version
run: |
NEW_VERSION=$(grep '^version = ' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT"
echo "New version: $NEW_VERSION"
- name: Build package
run: |
uv build
- name: Publish to PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
# --skip-existing: if a version already reached PyPI from a run that
# died before pushing its bump commit, warn instead of failing so the
# bump+tag still land and the next run moves past the collision.
run: uv run twine upload --verbose --skip-existing dist/*
- name: Push version bump and tag to GitHub
if: ${{ success() }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config --global user.name 'github-actions[bot]'
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
git add .
git commit -m "chore: bump version [ci skip]" || echo "No changes to commit"
TAG="v${{ steps.version.outputs.version }}"
# main can advance between our checkout and this push (a human or
# another branch landing a commit while we bump). The bare `git
# push` used to fail the whole publish with "fetch first". Rebase
# onto the latest main and retry instead of going red.
for attempt in 1 2 3 4 5; do
if ! git pull --rebase origin main 2>/dev/null; then
echo "rebase conflicted/running; aborting and retrying"
git rebase --abort 2>/dev/null || true
sleep 5
continue
fi
git tag -f -a "$TAG" -m "Release $TAG"
if git push origin main; then
git push origin "$TAG" || echo "tag $TAG already exists remotely (fine)"
echo "Pushed version bump and tag $TAG"
exit 0
fi
echo "Push rejected (attempt $attempt/5); retrying..."
sleep 5
done
echo "Giving up pushing version bump after 5 attempts"
exit 1