Merge pull request #3844 from dimagi/cs/fix_failing_test #8296
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 }} |