Skip to content

Merge pull request #3844 from dimagi/cs/fix_failing_test #8296

Merge pull request #3844 from dimagi/cs/fix_failing_test

Merge pull request #3844 from dimagi/cs/fix_failing_test #8296

Workflow file for this run

name: Lint and Test
on:
pull_request:
paths-ignore:
- 'components/**'
- 'docs/**'
- 'mkdocs.yml'
- 'README.md'
- 'CLAUDE.md'
- 'LICENSE'
- '.coderabbit.yaml'
- 'locust/**'
- 'cypress/**'
- 'cypress.config.ts'
- 'cypress.env.json'
- 'docker-compose-dev.yml'
- 'heroku.yml'
- 'app.json'
- 'scripts/**'
- 'media/**'
push:
branches:
- main
paths-ignore:
- 'components/**'
- 'docs/**'
- 'mkdocs.yml'
- 'README.md'
- 'CLAUDE.md'
- 'LICENSE'
- '.coderabbit.yaml'
- 'locust/**'
- 'cypress/**'
- 'cypress.config.ts'
- 'cypress.env.json'
- 'docker-compose-dev.yml'
- 'heroku.yml'
- 'app.json'
- 'scripts/**'
- 'media/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
PYTHON_VERSION: '3.13'
permissions:
contents: read
jobs:
build-image:
# Pre-build the prod container image (tagged by commit SHA) in parallel with
# the tests, so the Deploy workflow — which chains off this one — can skip the
# build and go straight to migrate + deploy. Only runs on main pushes, so
# PR/fork code never receives AWS credentials.
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- name: Set variables
run: |
APP_NAME="${{ fromJSON(vars.DEPLOY_APP_NAME)['prod'] }}"
echo "ECR_REPOSITORY=$APP_NAME-prod-ecr-repo" >> "$GITHUB_ENV"
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v6.2.1
with:
role-to-assume: "arn:aws:iam::${{ fromJSON(vars.AWS_ACCOUNT)['prod'] }}:role/github_deploy"
role-session-name: GithubBuild
aws-region: ${{ fromJSON(vars.DEPLOY_AWS_REGION)['prod'] }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2.1.6
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Get image names
id: image-name
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> "$GITHUB_OUTPUT"
echo "image_latest=$ECR_REGISTRY/$ECR_REPOSITORY:latest" >> "$GITHUB_OUTPUT"
- name: Build and push
uses: docker/build-push-action@v7
with:
tags: |
${{ steps.image-name.outputs.image }}
${{ steps.image-name.outputs.image_latest }}
file: Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
outputs: type=image,push=true,oci-mediatypes=true,compression=zstd,compression-level=3
build-frontend:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Use Node.js
uses: actions/setup-node@v6
with:
node-version: 24.x
- name: Install dependencies
run: npm ci
- name: Build front end
run: npm run build
- name: Check types
run: npm run type-check
code-style:
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: 24.x
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install dependencies
run: |
npm ci
sudo apt-get install -y ripgrep
uv venv
uv sync --locked --dev
- id: file_changes
uses: trilom/file-changes-action@v1.2.4
- id: changed_files
name: Build space-separated file list
env:
CHANGED_FILES: ${{ steps.file_changes.outputs.files }}
run: |
files=$(printf '%s' "$CHANGED_FILES" | jq -r '.[]' | tr '\n' ' ')
echo "files=$files" >> "$GITHUB_OUTPUT"
- name: Run pre-commit hooks
uses: j178/prek-action@v2
with:
extra-args: --files ${{ steps.changed_files.outputs.files }}
type-check:
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install dependencies
run: |
uv venv
uv sync --locked --dev
- name: Run ty type checker
run: uv run ty check apps/
inline-imports:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- uses: actions/checkout@v6
- id: file_changes
uses: trilom/file-changes-action@v1.2.4
- id: py_files
name: Filter changed Python files
env:
CHANGED_FILES: ${{ steps.file_changes.outputs.files }}
run: |
files=$(printf '%s' "$CHANGED_FILES" | jq -r '.[]' | grep -E '^apps/.*\.py$' | tr '\n' ' ' || true)
echo "files=$files" >> "$GITHUB_OUTPUT"
- name: Set up Python
if: steps.py_files.outputs.files != ''
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: astral-sh/setup-uv@v7
if: steps.py_files.outputs.files != ''
with:
enable-cache: true
- name: Install dependencies
if: steps.py_files.outputs.files != ''
run: |
uv venv
uv sync --locked --dev
- name: Check inline imports in changed files
if: steps.py_files.outputs.files != ''
env:
SECRET_KEY: secret-test-key
CHANGED_FILES: ${{ steps.py_files.outputs.files }}
run: |
read -r -a files <<< "$CHANGED_FILES"
uv run python scripts/check_inline_imports.py apps --files "${files[@]}"
check-uv-lock:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: astral-sh/setup-uv@v7
- name: Check lockfile
run: uv lock --check
python-tests:
runs-on: ubuntu-latest
timeout-minutes: 60
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres_password
POSTGRES_INITDB_ARGS: "--no-sync"
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
--tmpfs /var/lib/postgresql/data
ports:
- 5432:5432
redis:
image: redis
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379
steps:
- uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install Dependencies
run: |
uv venv
uv sync --locked --dev
- name: Configure Postgres for performance
run: |
PGPASSWORD=postgres_password psql -h localhost -U postgres \
-c "ALTER SYSTEM SET fsync = off;" \
-c "ALTER SYSTEM SET synchronous_commit = off;" \
-c "ALTER SYSTEM SET full_page_writes = off;" \
-c "ALTER SYSTEM SET checkpoint_completion_target = 0.9;" \
-c "SELECT pg_reload_conf();"
# Create extensions in template1 so test databases inherit them. This lets PR runs
# use --no-migrations (the extensions are normally created by a migration).
PGPASSWORD=postgres_password psql -h localhost -U postgres -d template1 \
-c "CREATE EXTENSION IF NOT EXISTS vector;" \
-c "CREATE EXTENSION IF NOT EXISTS pg_trgm;"
- name: Set test flags
id: test_flags
run: |
# On main, run with migrations (and coverage) so migrations stay exercised before deploy.
# On PRs, skip migrations for faster feedback.
if [ "$GITHUB_REF" = "refs/heads/main" ]; then
echo "flags=--cov --cov-report=xml" >> "$GITHUB_OUTPUT"
else
echo "flags=--no-migrations" >> "$GITHUB_OUTPUT"
fi
- name: Run Tests
env:
DJANGO_DATABASE_USER: postgres
DJANGO_DATABASE_PASSWORD: postgres_password
SECRET_KEY: secret-test-key
PYTHONWARNINGS: default
run: uv run pytest -n auto ${{ steps.test_flags.outputs.flags }} --junitxml=junit.xml -o junit_family=legacy
- name: Upload results to Codecov
if: ${{ !cancelled() && github.ref == 'refs/heads/main' }}
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
token: ${{ secrets.CODECOV_TOKEN }}