feat: add ty type checker to pre-k hooks (#2213)

Adds a local pre-commit hook for ty type checker since there's no
official pre-commit hook available yet (tracked in astral-sh/ty#269).
This commit is contained in:
Kevin Turcios 2026-01-09 22:36:53 -05:00 committed by GitHub
parent 7bef00afa3
commit 1e1820d27a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 128 additions and 984 deletions

View file

@ -9,6 +9,7 @@ on:
permissions:
contents: read
pull-requests: read
checks: read
defaults:
run:
@ -48,8 +49,21 @@ jobs:
- name: Skip optimization
run: echo "Skipping codeflash optimization - no changes in django/aiservice/"
optimize:
wait-for-prek:
needs: check-changes
if: needs.check-changes.outputs.should-run == 'true'
name: Wait for prek checks
runs-on: ubuntu-latest
steps:
- uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: prek
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
optimize:
needs: [check-changes, wait-for-prek]
if: needs.check-changes.outputs.should-run == 'true' && github.actor != 'codeflash-ai[bot]'
name: Optimize new code in this PR
runs-on: ubuntu-latest

View file

@ -13,6 +13,7 @@ defaults:
permissions:
contents: read
pull-requests: read
checks: read
jobs:
# This job checks if the workflow should run based on file changes
@ -45,10 +46,23 @@ jobs:
- name: Skip tests
run: echo "Skipping django unit tests - no changes in django/aiservice/"
unit-tests:
wait-for-prek:
name: Wait for prek checks
needs: check-changes
if: needs.check-changes.outputs.should-run == 'true'
runs-on: ubuntu-latest
steps:
- uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
check-name: prek
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
unit-tests:
needs: [check-changes, wait-for-prek]
if: needs.check-changes.outputs.should-run == 'true'
runs-on: ubuntu-latest
env:
SECRET_KEY: ${{ secrets.SECRET_KEY }}
@ -78,7 +92,7 @@ jobs:
django-unit-tests-status:
runs-on: ubuntu-latest
needs: [check-changes, no-aiservice-changes, unit-tests]
needs: [check-changes, no-aiservice-changes, wait-for-prek, unit-tests]
if: always()
defaults:
run:

View file

@ -1,159 +0,0 @@
name: end-to-end-test
on:
pull_request:
workflow_run:
workflows: ["django-unit-tests"]
types:
- completed
branches: [main]
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
check-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.filter.outputs.relevant == 'true' || github.event_name == 'workflow_dispatch' }}
aiservice_changed: ${{ steps.filter.outputs.aiservice == 'true' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check which projects changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
relevant:
- 'django/aiservice/**'
- '.github/workflows/end-to-end-test-bubblesort-unittest.yaml'
aiservice:
- 'django/aiservice/**'
no-changes-detected:
name: No relevant changes detected
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run != 'true' }}
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end test"
- name: Mark as success
run: exit 0
unit-tests-check:
name: Wait for unit tests
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Wait for unit tests to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: 'unit-tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
bubble-sort-optimization-unittest:
needs: [check-changes, unit-tests-check]
if: |
always() &&
(needs.unit-tests-check.result == 'success' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
AZURE_ANTHROPIC_API_KEY: ${{ secrets.AZURE_ANTHROPIC_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
CODEFLASH_API_KEY: ${{ secrets.CODEFLASH_API_KEY }}
COLUMNS: 110
MAX_RETRIES: 3
RETRY_DELAY: 5
EXPECTED_IMPROVEMENT_PCT: 40
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.12 for AI Server
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Install dependencies for Django server
run: |
cd ./django/aiservice
uv sync
- name: Start Django server
run: |
cd ./django/aiservice
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Clone codeflash repo
run: |
cd ..
git clone https://github.com/codeflash-ai/codeflash.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.11 for CLI
uses: actions/setup-python@v5
with:
python-version: "3.11.6"
- name: Install dependencies (CLI)
run: |
cd ../codeflash
uv sync
uv add sqlalchemy
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_bubblesort_unittest.py
- name: Display AI Server logs
if: always()
run: |
cd ./django/aiservice
cat server.log
bubble-sort-unittest-status:
runs-on: ubuntu-latest
needs: [check-changes, no-changes-detected, unit-tests-check, bubble-sort-optimization-unittest]
if: always()
steps:
- name: Check all job statuses
run: |
if [[ "${{ needs.bubble-sort-optimization-unittest.result }}" == "success" ]] || \
[[ "${{ needs.bubble-sort-optimization-unittest.result }}" == "skipped" ]] || \
[[ "${{ needs.no-changes-detected.result }}" == "success" ]]; then
echo "✓ Bubble sort unittest workflow completed successfully"
exit 0
else
echo "✗ Bubble sort unittest workflow failed"
exit 1
fi

View file

@ -1,144 +0,0 @@
name: Coverage E2E
on:
pull_request:
paths:
- "django/aiservice/**"
- ".github/workflows/end-to-end-test-coverage.yaml"
workflow_run:
workflows: ["django-unit-tests"]
types:
- completed
branches: [main]
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
check-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.filter.outputs.relevant == 'true' || github.event_name == 'workflow_dispatch' }}
aiservice_changed: ${{ steps.filter.outputs.aiservice == 'true' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check which projects changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
relevant:
- 'django/aiservice/**'
- '.github/workflows/end-to-end-test-coverage.yaml'
aiservice:
- 'django/aiservice/**'
no-changes-detected:
name: No relevant changes detected
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run != 'true' }}
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end test"
- name: Mark as success
run: exit 0
unit-tests-check:
name: Wait for unit tests
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Wait for unit tests to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: 'unit-tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
end-to-end-test-coverage:
needs: [check-changes, unit-tests-check]
if: |
always() &&
(needs.unit-tests-check.result == 'success' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
AZURE_ANTHROPIC_API_KEY: ${{ secrets.AZURE_ANTHROPIC_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
CODEFLASH_API_KEY: ${{ secrets.CODEFLASH_API_KEY }}
MAX_RETRIES: 3
RETRY_DELAY: 5
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.12 for AI Server
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Install dependencies for Django server
run: |
cd ./django/aiservice
uv sync
- name: Start Django server
run: |
cd ./django/aiservice
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Clone codeflash repo
run: |
cd ..
git clone https://github.com/codeflash-ai/codeflash.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.11 for CLI
uses: actions/setup-python@v5
with:
python-version: "3.11.6"
- name: Install dependencies (CLI)
run: |
cd ../codeflash
uv sync
uv add sqlalchemy black
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_coverage.py
- name: Display AI Server logs
if: always()
run: |
cd ./django/aiservice
cat server.log

View file

@ -1,160 +0,0 @@
name: end-to-end-test
on:
pull_request:
workflow_run:
workflows: ["django-unit-tests"]
types:
- completed
branches: [main]
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
check-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.filter.outputs.relevant == 'true' || github.event_name == 'workflow_dispatch' }}
aiservice_changed: ${{ steps.filter.outputs.aiservice == 'true' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check which projects changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
relevant:
- 'django/aiservice/**'
- '.github/workflows/end-to-end-test-futurehouse.yaml'
aiservice:
- 'django/aiservice/**'
no-changes-detected:
name: No relevant changes detected
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run != 'true' }}
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end test"
- name: Mark as success
run: exit 0
unit-tests-check:
name: Wait for unit tests
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Wait for unit tests to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: 'unit-tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
futurehouse-structure:
needs: [check-changes, unit-tests-check]
if: |
always() &&
(needs.unit-tests-check.result == 'success' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
AZURE_ANTHROPIC_API_KEY: ${{ secrets.AZURE_ANTHROPIC_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
CODEFLASH_API_KEY: ${{ secrets.CODEFLASH_API_KEY }}
COLUMNS: 110
MAX_RETRIES: 3
RETRY_DELAY: 5
EXPECTED_IMPROVEMENT_PCT: 10
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.12 for AI Server
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Install dependencies for Django server
run: |
cd ./django/aiservice
uv sync
- name: Start Django server
run: |
cd ./django/aiservice
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Clone codeflash repo
run: |
cd ..
git clone https://github.com/codeflash-ai/codeflash.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.11 for CLI
uses: actions/setup-python@v5
with:
python-version: "3.11.6"
- name: Install dependencies (CLI)
run: |
cd ../codeflash
uv sync
uv add sqlalchemy
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_futurehouse.py
- name: Display AI Server logs
if: always()
run: |
cd ./django/aiservice
cat server.log
futurehouse-status:
runs-on: ubuntu-latest
needs: [check-changes, no-changes-detected, unit-tests-check, futurehouse-structure]
if: always()
steps:
- name: Check all job statuses
run: |
if [[ "${{ needs.futurehouse-structure.result }}" == "success" ]] || \
[[ "${{ needs.futurehouse-structure.result }}" == "skipped" ]] || \
[[ "${{ needs.no-changes-detected.result }}" == "success" ]]; then
echo "✓ Futurehouse workflow completed successfully"
exit 0
else
echo "✗ Futurehouse workflow failed"
exit 1
fi

View file

@ -1,145 +0,0 @@
name: end-to-end-test
on:
pull_request:
paths:
- "django/aiservice/**"
- ".github/workflows/end-to-end-test-init-optim.yaml"
workflow_run:
workflows: ["django-unit-tests"]
types:
- completed
branches: [main]
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
check-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.filter.outputs.relevant == 'true' || github.event_name == 'workflow_dispatch' }}
aiservice_changed: ${{ steps.filter.outputs.aiservice == 'true' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check which projects changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
relevant:
- 'django/aiservice/**'
- '.github/workflows/end-to-end-test-init-optim.yaml'
aiservice:
- 'django/aiservice/**'
no-changes-detected:
name: No relevant changes detected
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run != 'true' }}
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end test"
- name: Mark as success
run: exit 0
unit-tests-check:
name: Wait for unit tests
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Wait for unit tests to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: 'unit-tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
init-optimization:
needs: [check-changes, unit-tests-check]
if: |
always() &&
(needs.unit-tests-check.result == 'success' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
AZURE_ANTHROPIC_API_KEY: ${{ secrets.AZURE_ANTHROPIC_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
CODEFLASH_API_KEY: ${{ secrets.CODEFLASH_API_KEY }}
COLUMNS: 110
MAX_RETRIES: 3
RETRY_DELAY: 5
EXPECTED_IMPROVEMENT_PCT: 10
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.12 for AI Server
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Install dependencies for Django server
run: |
cd ./django/aiservice
uv sync
- name: Start Django server
run: |
cd ./django/aiservice
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Clone codeflash repo
run: |
cd ..
git clone https://github.com/codeflash-ai/codeflash.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.11 for CLI
uses: actions/setup-python@v5
with:
python-version: "3.11.6"
- name: Install dependencies (CLI)
run: |
cd ../codeflash
uv sync
uv add sqlalchemy
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_init_optimization.py
- name: Display AI Server logs
if: always()
run: |
cd ./django/aiservice
cat server.log

View file

@ -1,161 +0,0 @@
name: end-to-end-test
on:
pull_request:
workflow_run:
workflows: ["django-unit-tests"]
types:
- completed
branches: [main]
workflow_dispatch:
# Add explicit permissions for the GITHUB_TOKEN
permissions:
contents: read
pull-requests: read
jobs:
check-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.filter.outputs.relevant == 'true' || github.event_name == 'workflow_dispatch' }}
aiservice_changed: ${{ steps.filter.outputs.aiservice == 'true' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check which projects changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
relevant:
- 'django/aiservice/**'
- 'cli/**'
- '.github/workflows/end-to-end-test-tracer-replay.yaml'
aiservice:
- 'django/aiservice/**'
no-changes-detected:
name: No relevant changes detected
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run != 'true' }}
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end tests"
- name: Mark as success
run: exit 0
unit-tests-check:
name: Wait for unit tests
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Wait for unit tests to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: 'unit-tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
tracer-replay:
needs: [check-changes, unit-tests-check]
if: |
always() &&
(needs.unit-tests-check.result == 'success' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
AZURE_ANTHROPIC_API_KEY: ${{ secrets.AZURE_ANTHROPIC_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
CODEFLASH_API_KEY: ${{ secrets.CODEFLASH_API_KEY }}
COLUMNS: 110
MAX_RETRIES: 3
RETRY_DELAY: 5
EXPECTED_IMPROVEMENT_PCT: 10
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.12 for AI Server
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Install dependencies for Django server
run: |
cd ./django/aiservice
uv sync
- name: Start Django server
run: |
cd ./django/aiservice
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Clone codeflash repo
run: |
cd ..
git clone https://github.com/codeflash-ai/codeflash.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.11 for CLI
uses: actions/setup-python@v5
with:
python-version: "3.11.6"
- name: Install dependencies (CLI)
run: |
cd ../codeflash
uv sync
uv add sqlalchemy
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_tracer_replay.py
- name: Display AI Server logs
if: always()
run: |
cd ./django/aiservice
cat server.log
tracer-replay-status:
runs-on: ubuntu-latest
needs: [check-changes, no-changes-detected, unit-tests-check, tracer-replay]
if: always()
steps:
- name: Check all job statuses
run: |
if [[ "${{ needs.tracer-replay.result }}" == "success" ]] || \
[[ "${{ needs.tracer-replay.result }}" == "skipped" ]] || \
[[ "${{ needs.no-changes-detected.result }}" == "success" ]]; then
echo "✓ Tracer replay workflow completed successfully"
exit 0
else
echo "✗ Tracer replay workflow failed"
exit 1
fi

View file

@ -1,4 +1,4 @@
name: end-to-end-test
name: end-to-end-tests
on:
pull_request:
@ -34,7 +34,8 @@ jobs:
filters: |
relevant:
- 'django/aiservice/**'
- '.github/workflows/end-to-end-test-bubblesort-pytest-no-git.yaml'
- 'cli/**'
- '.github/workflows/end-to-end-tests.yaml'
aiservice:
- 'django/aiservice/**'
@ -45,13 +46,30 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end test"
run: echo "No relevant changes detected, skipping end-to-end tests"
- name: Mark as success
run: exit 0
prek-check:
name: Wait for prek checks
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: prek
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
unit-tests-check:
name: Wait for unit tests
needs: check-changes
needs: [check-changes, prek-check]
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
@ -68,7 +86,8 @@ jobs:
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
bubble-sort-optimization-pytest-no-git:
e2e-test:
name: ${{ matrix.name }}
needs: [check-changes, unit-tests-check]
if: |
always() &&
@ -76,6 +95,33 @@ jobs:
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: bubblesort-pytest-no-git
script: end_to_end_test_bubblesort_pytest.py
expected_improvement: 70
remove_git: true
- name: bubblesort-unittest
script: end_to_end_test_bubblesort_unittest.py
expected_improvement: 40
- name: coverage
script: end_to_end_test_coverage.py
expected_improvement: 10
extra_deps: black
- name: futurehouse
script: end_to_end_test_futurehouse.py
expected_improvement: 10
- name: init-optimization
script: end_to_end_test_init_optimization.py
expected_improvement: 10
- name: tracer-replay
script: end_to_end_test_tracer_replay.py
expected_improvement: 10
- name: topological-sort
script: end_to_end_test_topological_sort_worktree.py
expected_improvement: 5
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
@ -88,7 +134,7 @@ jobs:
COLUMNS: 110
MAX_RETRIES: 3
RETRY_DELAY: 5
EXPECTED_IMPROVEMENT_PCT: 70
EXPECTED_IMPROVEMENT_PCT: ${{ matrix.expected_improvement }}
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
@ -113,6 +159,7 @@ jobs:
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Remove .git
if: ${{ matrix.remove_git == true }}
run: |
if [ -d ".git" ]; then
echo ".git directory exists!"
@ -144,13 +191,13 @@ jobs:
run: |
cd ../codeflash
uv sync
uv add sqlalchemy
uv add sqlalchemy ${{ matrix.extra_deps }}
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_bubblesort_pytest.py
uv run python tests/scripts/${{ matrix.script }}
- name: Display AI Server logs
if: always()
@ -158,22 +205,24 @@ jobs:
cd ./django/aiservice
cat server.log
bubble-sort-pytest-no-git-status:
e2e-status:
name: E2E Tests Status
runs-on: ubuntu-latest
needs: [check-changes, no-changes-detected, unit-tests-check, bubble-sort-optimization-pytest-no-git]
needs: [check-changes, no-changes-detected, prek-check, unit-tests-check, e2e-test]
if: always()
steps:
- name: Check all job statuses
run: |
if [[ "${{ needs.bubble-sort-optimization-pytest-no-git.result }}" == "success" ]] || \
[[ "${{ needs.bubble-sort-optimization-pytest-no-git.result }}" == "skipped" ]] || \
if [[ "${{ needs.e2e-test.result }}" == "success" ]] || \
[[ "${{ needs.e2e-test.result }}" == "skipped" ]] || \
[[ "${{ needs.no-changes-detected.result }}" == "success" ]]; then
echo "✓ Bubble sort pytest no-git workflow completed successfully"
echo "✓ End-to-end tests workflow completed successfully"
exit 0
else
echo "✗ Bubble sort pytest no-git workflow failed"
echo "✗ End-to-end tests workflow failed"
echo "no-changes-detected: ${{ needs.no-changes-detected.result }}"
echo "prek-check: ${{ needs.prek-check.result }}"
echo "unit-tests-check: ${{ needs.unit-tests-check.result }}"
echo "bubble-sort-optimization-pytest-no-git: ${{ needs.bubble-sort-optimization-pytest-no-git.result }}"
echo "e2e-test: ${{ needs.e2e-test.result }}"
exit 1
fi

View file

@ -1,160 +0,0 @@
name: end-to-end-test
on:
pull_request:
workflow_run:
workflows: ["django-unit-tests"]
types:
- completed
branches: [main]
workflow_dispatch:
permissions:
contents: read
pull-requests: read
jobs:
check-changes:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
should_run: ${{ steps.filter.outputs.relevant == 'true' || github.event_name == 'workflow_dispatch' }}
aiservice_changed: ${{ steps.filter.outputs.aiservice == 'true' }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check which projects changed
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
relevant:
- 'django/aiservice/**'
- '.github/workflows/end-to-end-topological-sort-test.yaml'
aiservice:
- 'django/aiservice/**'
no-changes-detected:
name: No relevant changes detected
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.should_run != 'true' }}
runs-on: ubuntu-latest
steps:
- name: Skip test
run: echo "No relevant changes detected, skipping end-to-end test"
- name: Mark as success
run: exit 0
unit-tests-check:
name: Wait for unit tests
needs: check-changes
if: ${{ github.event_name == 'pull_request' && needs.check-changes.outputs.aiservice_changed == 'true' }}
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
checks: read
steps:
- uses: actions/checkout@v4
- name: Wait for unit tests to pass
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ github.event.pull_request.head.sha }}
check-name: 'unit-tests'
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
topological-sort-optimization:
needs: [check-changes, unit-tests-check]
if: |
always() &&
(needs.unit-tests-check.result == 'success' ||
(github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') ||
github.event_name == 'workflow_dispatch')
runs-on: ubuntu-latest
env:
CODEFLASH_AIS_SERVER: local
AZURE_OPENAI_API_KEY: ${{ secrets.AZURE_OPENAI_API_KEY }}
OPENAI_API_TYPE: ${{ secrets.OPENAI_API_TYPE }}
OPENAI_API_BASE: ${{ secrets.OPENAI_API_BASE }}
AZURE_ANTHROPIC_API_KEY: ${{ secrets.AZURE_ANTHROPIC_API_KEY }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
POSTHOG_API_KEY: ${{ secrets.POSTHOG_API_KEY }}
CODEFLASH_API_KEY: ${{ secrets.CODEFLASH_API_KEY }}
COLUMNS: 110
MAX_RETRIES: 3
RETRY_DELAY: 5
EXPECTED_IMPROVEMENT_PCT: 5
CODEFLASH_END_TO_END: 1
steps:
- name: Check out codeflash-internal repo
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.12 for AI Server
uses: astral-sh/setup-uv@v7
with:
python-version: "3.12"
- name: Install dependencies for Django server
run: |
cd ./django/aiservice
uv sync
- name: Start Django server
run: |
cd ./django/aiservice
uv run uvicorn aiservice.asgi:application --host localhost --port 8000 >> server.log 2>&1 &
- name: Clone codeflash repo
run: |
cd ..
git clone https://github.com/codeflash-ai/codeflash.git
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python 3.11 for CLI
uses: actions/setup-python@v5
with:
python-version: "3.11.6"
- name: Install dependencies (CLI)
run: |
cd ../codeflash
uv sync
uv add sqlalchemy
- name: Run Codeflash to optimize code
id: optimize_code
run: |
cd ../codeflash
uv run python tests/scripts/end_to_end_test_topological_sort_worktree.py
- name: Display AI Server logs
if: always()
run: |
cd ./django/aiservice
cat server.log
topological-sort-status:
runs-on: ubuntu-latest
needs: [check-changes, no-changes-detected, unit-tests-check, topological-sort-optimization]
if: always()
steps:
- name: Check all job statuses
run: |
if [[ "${{ needs.topological-sort-optimization.result }}" == "success" ]] || \
[[ "${{ needs.topological-sort-optimization.result }}" == "skipped" ]] || \
[[ "${{ needs.no-changes-detected.result }}" == "success" ]]; then
echo "✓ Topological sort workflow completed successfully"
exit 0
else
echo "✗ Topological sort workflow failed"
exit 1
fi

View file

@ -8,6 +8,7 @@ jobs:
- uses: actions/checkout@v5
with:
fetch-depth: 0
- uses: astral-sh/setup-uv@v5
- uses: j178/prek-action@v1
with:
extra-args: '--from-ref origin/${{ github.base_ref }} --to-ref ${{ github.sha }}'

View file

@ -2,17 +2,21 @@ repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.10
hooks:
# Run the linter.
# Disabled since there are a lot of existing linting issues
# - id: ruff-check
# args: [ --fix ]
# Run the formatter.
- id: ruff-format
- repo: local
hooks:
- id: ty
name: ty (type checker)
entry: uv run ty check
# Disabled for now - many existing linting issues to fix
# - id: ruff-check
# name: ruff linter
# entry: uv run -q ruff check
# language: system
# types: [python]
# pass_filenames: true
- id: ty-check
name: ty type checker
entry: uv run -q ty check
language: system
types: [python]
pass_filenames: true

View file

@ -23,11 +23,7 @@ from optimizer.models import OptimizedCandidateSource
from .adaptive_optimizer_context import AdaptiveOptContext, AdaptiveOptContextData, AdaptiveOptRequestSchema
if TYPE_CHECKING:
from openai.types.chat import (
ChatCompletionAssistantMessageParam,
ChatCompletionFunctionMessageParam,
ChatCompletionToolMessageParam,
)
from openai.types.chat import ChatCompletionMessageParam
from aiservice.llm import LLM
@ -54,19 +50,13 @@ USER_PROMPT = (current_dir / "ADAPTIVE_OPTIMIZER_USER_PROMPT.md").read_text()
async def perform_adaptive_optimize(
user_id: str, ctx: AdaptiveOptContext, optimize_model: LLM = ADAPTIVE_OPTIMIZE_MODEL
) -> tuple[OptimizeResponseItemSchema, float, AdaptiveOptErrorResponseSchema]:
) -> tuple[OptimizeResponseItemSchema | None, float | None, AdaptiveOptErrorResponseSchema | None]:
system_prompt = ctx.get_system_prompt()
user_prompt = ctx.get_user_prompt()
system_message = ChatCompletionSystemMessageParam(role="system", content=system_prompt)
user_message = ChatCompletionUserMessageParam(role="user", content=user_prompt)
messages: list[
ChatCompletionSystemMessageParam
| ChatCompletionUserMessageParam
| ChatCompletionAssistantMessageParam
| ChatCompletionToolMessageParam
| ChatCompletionFunctionMessageParam
] = [system_message, user_message]
messages: list[ChatCompletionMessageParam] = [system_message, user_message]
debug_log_sensitive_data(f"This was the user prompt\n {user_prompt}\n")
try:
output = await call_llm(llm=optimize_model, messages=messages)
@ -94,11 +84,8 @@ async def perform_adaptive_optimize(
ctx.extract_code_and_explanation_from_llm_res(llm_res)
new_opt = ctx.parse_and_generate_candidate_schema()
if not new_opt or not ctx.is_valid_code():
return (
None,
None,
AdaptiveOptErrorResponseSchema(error="Invalid code generated " + str(ctx.extracted_code_and_expl.code)),
)
extracted_code = ctx.extracted_code_and_expl.code if ctx.extracted_code_and_expl else None
return (None, None, AdaptiveOptErrorResponseSchema(error="Invalid code generated " + str(extracted_code)))
# the parent is the last candidate in the previous optimizations
last_optimization_id = ctx.data.attempts[-1].optimization_id
@ -106,7 +93,7 @@ async def perform_adaptive_optimize(
return new_opt, llm_cost, None # noqa: TRY300
except (ValueError, ValidationError, cst.ParserSyntaxError) as exc:
sentry_sdk.capture_exception(exc)
debug_log_sensitive_data(f"{type(exc).__name__} for source:\n{ctx.data.modified_source_code}")
debug_log_sensitive_data(f"{type(exc).__name__} for source:\n{ctx.data.original_source_code}")
debug_log_sensitive_data(f"Traceback: {exc}")
return None, None, AdaptiveOptErrorResponseSchema(error=str(exc))
@ -135,7 +122,10 @@ async def adaptive_optimize(
total_llm_cost = 0.0
if error:
return 500, error
total_llm_cost += llm_cost
if adaptive_optimization_candidate is None:
return 500, AdaptiveOptErrorResponseSchema(error="Failed to generate optimization candidate")
if llm_cost is not None:
total_llm_cost += llm_cost
if hasattr(request, "should_log_features") and request.should_log_features:
await log_features(

View file

@ -40,7 +40,7 @@ class AdaptiveOptContext(MultiOptimizerContext):
self.extracted_code_and_expl: CodeStrAndExplanation | None = None
super().__init__(base_system_prompt, base_user_prompt, ctx_data.original_source_code, DiffMethod.NO_DIFF)
def get_system_prompt(self) -> str:
def get_system_prompt(self, python_version_str: str | None = None) -> str: # noqa: ARG002
return self.base_system_prompt.format(python_version_str=self.data.python_version_str)
def build_attempts_str(self) -> str:
@ -52,7 +52,7 @@ class AdaptiveOptContext(MultiOptimizerContext):
attempts_str += f"**\n{attempt.speedup}\n**"
return attempts_str
def get_user_prompt(self) -> str:
def get_user_prompt(self, dependency_code: str = "", line_profiler_results: str | None = None) -> str: # noqa: ARG002
return self.base_user_prompt.format(
ORIGINAL_CODE=self.data.original_source_code, OPTIMIZATION_ATTEMPTS=self.build_attempts_str()
)

View file

@ -82,6 +82,7 @@ class Users(models.Model):
class Organizations(models.Model):
objects: ClassVar[models.Manager[Organizations]]
id = models.CharField(primary_key=True, max_length=36)
name = models.CharField(max_length=255, unique=True)
github_org_id = models.CharField(max_length=255, null=True, blank=True, unique=True)

View file

@ -44,7 +44,7 @@ class UsedNameCollector(CSTVisitor):
self.used_names.add(base.value.attr.value)
return True
def leave_ClassDef(self, node: ClassDef) -> None:
def leave_ClassDef(self, original_node: ClassDef) -> None: # noqa: ARG002
self.currently_defining = None
def visit_FunctionDef(self, node: FunctionDef) -> bool:
@ -52,7 +52,7 @@ class UsedNameCollector(CSTVisitor):
self.currently_defining = node.name.value
return True
def leave_FunctionDef(self, node: FunctionDef) -> None:
def leave_FunctionDef(self, original_node: FunctionDef) -> None: # noqa: ARG002
self.currently_defining = None
def visit_Call(self, node: Call) -> bool:

View file

@ -7,7 +7,7 @@ from testgen.testgen_context import any_ellipsis_in_ast, ellipsis_in_ast_not_typ
class TestEllipsisInAst(TestCase):
@unittest.skip
@unittest.skip("skip test_ellipsis_in_ast_with_ellipsis")
def test_ellipsis_in_ast_with_ellipsis(self) -> None:
"""Test that ellipsis_in_ast detects an ellipsis in the function body."""
code = """
@ -17,7 +17,7 @@ def example_function():
module = ast.parse(code)
assert ellipsis_in_ast_not_types(module) is True
@unittest.skip
@unittest.skip("skip test_ellipsis_in_ast_without_ellipsis")
def test_ellipsis_in_ast_without_ellipsis(self) -> None:
"""Test that ellipsis_in_ast does not detect an ellipsis when there is none."""
code = """
@ -27,7 +27,7 @@ def example_function():
module = ast.parse(code)
assert ellipsis_in_ast_not_types(module) is False
@unittest.skip
@unittest.skip("skip test_ellipsis_in_ast_in_type_annotation")
def test_ellipsis_in_ast_in_type_annotation(self) -> None:
"""Test that ellipsis_in_ast ignores ellipses in type annotations."""
code = """
@ -37,7 +37,7 @@ def example_function(param: tuple[int, ...]) -> None:
module = ast.parse(code)
assert ellipsis_in_ast_not_types(module) is False
@unittest.skip
@unittest.skip("skip test_ellipsis_in_ast_in_type_annotation_union")
def test_ellipsis_in_ast_in_type_annotation_union(self) -> None:
"""Test that ellipsis_in_ast ignores ellipses in type annotations with unions."""
code = """
@ -47,7 +47,7 @@ def example_function(param: tuple[int, ...] | list[int]) -> None:
module = ast.parse(code)
assert ellipsis_in_ast_not_types(module) is False
@unittest.skip
@unittest.skip("skip test_ellipsis_in_ast")
def test_ellipsis_in_ast(self) -> None:
code = """def example_fn():
return ..."""