name: unit-tests permissions: contents: read on: pull_request: merge_group: push: branches: - master concurrency: # We only need to be running tests for the latest commit on each PR # (however, we fully test every commit on master, even as new ones land). group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} jobs: run-tests: name: ${{ matrix.shard_name }}(py=${{ matrix.python-version }},dj=${{ matrix.django-version }},mongo=${{ matrix.mongo-version }}) runs-on: ${{ matrix.os-version }} strategy: matrix: python-version: - "3.11" - "3.12" django-version: - "pinned" # When updating the shards, remember to make the same changes in # .github/workflows/unit-tests-gh-hosted.yml shard_name: - "lms-1" - "lms-2" - "lms-3" - "lms-4" - "lms-5" - "lms-6" - "openedx-1-with-lms" - "openedx-2-with-lms" - "openedx-1-with-cms" - "openedx-2-with-cms" - "cms-1" - "cms-2" - "common-with-lms" - "common-with-cms" - "xmodule-with-lms" - "xmodule-with-cms" mongo-version: - "7.0" os-version: - ubuntu-24.04 # It's useful to run some subset of the tests on the older version of Ubuntu # so that we don't spend too many resources on this but can find major issues quickly # while we're in a situation where we support two versions. This section may be commented # out when not in use to easily add/drop future support for any given major dependency. # # We're testing the older version of Ubuntu and running the xmodule tests since those rely on many # dependent complex libraries and will hopefully catch most issues quickly. include: - shard_name: "xmodule-with-cms" python-version: "3.11" django-version: "pinned" mongo-version: "7.0" os-version: "ubuntu-22.04" - shard_name: "xmodule-with-lms" python-version: "3.11" django-version: "pinned" mongo-version: "7.0" os-version: "ubuntu-22.04" steps: - name: checkout repo uses: actions/checkout@v6 - name: install system requirements run: | sudo apt-get update && sudo apt-get install libmysqlclient-dev libxmlsec1-dev lynx # We pull this image a lot, and Dockerhub will rate limit us if we pull too often. # This is an attempt to cache the image for better performance and to work around that. # It will cache all pulled images, so if we add new images to this we'll need to update the key. - name: Cache Docker images uses: ScribeMD/docker-cache@0.5.0 with: key: docker-${{ runner.os }}-mongo-${{ matrix.mongo-version }} - name: Start MongoDB uses: supercharge/mongodb-github-action@1.12.1 with: mongodb-version: ${{ matrix.mongo-version }} - name: Setup Python uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: install requirements run: | make test-requirements if [[ "${{ matrix.django-version }}" != "pinned" ]]; then pip install "django~=${{ matrix.django-version }}.0" pip check # fail if this test-reqs/Django combination is broken fi - name: list installed package versions run: | pip freeze - name: set settings path shell: bash run: | echo "settings_path=$(python scripts/unit_test_shards_parser.py --shard-name=${{ matrix.shard_name }} --output settings )" >> $GITHUB_ENV - name: get unit tests for shard shell: bash run: | echo "unit_test_paths=$(python scripts/unit_test_shards_parser.py --shard-name=${{ matrix.shard_name }} )" >> $GITHUB_ENV - name: run tests shell: bash run: | python -Wd -m pytest -p no:randomly --ds=${{ env.settings_path }} ${{ env.unit_test_paths }} --cov=. - name: rename warnings json file if: success() shell: bash run: | cd test_root/log mv pytest_warnings.json pytest_warnings_${{ matrix.shard_name }}_${{ matrix.python-version }}_${{ matrix.django-version }}_${{ matrix.mongo-version }}_${{ matrix.os-version }}.json - name: save pytest warnings json file if: success() uses: actions/upload-artifact@v7 with: name: pytest-warnings-json-${{ matrix.shard_name }}-${{ matrix.python-version }}-${{ matrix.django-version }}-${{ matrix.mongo-version }}-${{ matrix.os-version }} path: | test_root/log/pytest_warnings*.json overwrite: true - name: Renaming coverage data file run: | mv reports/.coverage reports/${{ matrix.shard_name }}_${{ matrix.python-version }}_${{ matrix.django-version }}_${{ matrix.mongo-version }}_${{ matrix.os-version }}.coverage - name: Upload coverage uses: actions/upload-artifact@v7 with: name: coverage-${{ matrix.shard_name }}-${{ matrix.python-version }}-${{ matrix.django-version }}-${{ matrix.mongo-version }}-${{ matrix.os-version }} path: reports/${{ matrix.shard_name }}_${{ matrix.python-version }}_${{ matrix.django-version }}_${{ matrix.mongo-version }}_${{ matrix.os-version }}.coverage overwrite: true collect-and-verify: runs-on: ubuntu-24.04 steps: - uses: actions/checkout@v6 - name: Setup Python uses: actions/setup-python@v6 with: python-version: 3.11 - name: install system requirements run: | sudo apt-get update && sudo apt-get install libxmlsec1-dev - name: install requirements run: | make test-requirements - name: collect tests from all modules shell: bash run: | echo "root_cms_unit_tests_count=$(pytest --disable-warnings --collect-only --ds=cms.envs.test cms/ -q | head -n -2 | wc -l)" >> $GITHUB_ENV echo "root_lms_unit_tests_count=$(pytest --disable-warnings --collect-only --ds=lms.envs.test lms/ openedx/ common/djangoapps/ xmodule/ -q | head -n -2 | wc -l)" >> $GITHUB_ENV - name: get GHA unit test paths shell: bash run: | echo "cms_unit_test_paths=$(python scripts/gha_unit_tests_collector.py --cms-only)" >> $GITHUB_ENV echo "lms_unit_test_paths=$(python scripts/gha_unit_tests_collector.py --lms-only)" >> $GITHUB_ENV - name: collect tests from GHA unit test shards shell: bash run: | echo "cms_unit_tests_count=$(pytest --disable-warnings --collect-only --ds=cms.envs.test ${{ env.cms_unit_test_paths }} -q | head -n -2 | wc -l)" >> $GITHUB_ENV echo "lms_unit_tests_count=$(pytest --disable-warnings --collect-only --ds=lms.envs.test ${{ env.lms_unit_test_paths }} -q | head -n -2 | wc -l)" >> $GITHUB_ENV - name: add unit tests count shell: bash run: | echo "root_all_unit_tests_count=$((${{ env.root_cms_unit_tests_count }}+${{ env.root_lms_unit_tests_count }}))" >> $GITHUB_ENV echo "shards_all_unit_tests_count=$((${{ env.cms_unit_tests_count }}+${{ env.lms_unit_tests_count }}))" >> $GITHUB_ENV - name: print unit tests count shell: bash run: | echo CMS unit tests from root: ${{ env.root_cms_unit_tests_count }} echo LMS unit tests from root: ${{ env.root_lms_unit_tests_count }} echo CMS unit tests from shards: ${{ env.cms_unit_tests_count }} echo LMS unit tests from shards: ${{ env.lms_unit_tests_count }} echo All root unit tests count: ${{ env.root_all_unit_tests_count }} echo All shards unit tests count: ${{ env.shards_all_unit_tests_count }} - name: fail the check shell: bash if: ${{ env.root_all_unit_tests_count != env.shards_all_unit_tests_count }} run: | echo "::error title='Unit test modules in unit-test-shards.json (unit-tests.yml workflow) are outdated'::unit tests running in unit-tests workflow don't match the count for unit tests for entire openedx-platform suite, please update the unit-test-shards.json under .github/workflows to add any missing apps and match the count. for more details please take a look at scripts/gha-shards-readme.md" exit 1 # This job aggregates test results. It's the required check for branch protection. # https://github.com/marketplace/actions/alls-green#why # https://github.com/orgs/community/discussions/33579 success: name: Unit tests successful runs-on: ubuntu-24.04 if: always() needs: [run-tests] steps: - name: Decide whether the needed jobs succeeded or failed # uses: re-actors/alls-green@v1.2.1 uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe with: jobs: ${{ toJSON(needs) }} compile-warnings-report: runs-on: ubuntu-24.04 needs: [run-tests] steps: - uses: actions/checkout@v6 - name: collect pytest warnings files uses: actions/download-artifact@v8 with: pattern: pytest-warnings-json-* merge-multiple: true path: test_root/log - name: display structure of downloaded files run: ls -la test_root/log - name: compile warnings report run: | python openedx/core/process_warnings.py --dir-path test_root/log --html-path reports/pytest_warnings/warning_report_all.html - name: save warning report if: success() uses: actions/upload-artifact@v7 with: name: pytest-warning-report-html path: | reports/pytest_warnings/warning_report_all.html overwrite: true merge-artifacts: runs-on: ubuntu-24.04 needs: [compile-warnings-report] steps: - name: Merge Pytest Warnings JSON Artifacts uses: actions/upload-artifact/merge@v7 with: name: pytest-warnings-json pattern: pytest-warnings-json-* delete-merged: true - name: Merge Coverage Artifacts uses: actions/upload-artifact/merge@v7 with: name: coverage pattern: coverage-* delete-merged: true # Combine and upload coverage reports. coverage: if: (github.repository == 'edx/edx-platform-private') || (github.repository == 'openedx/openedx-platform' && (startsWith(github.base_ref, 'release') == false)) runs-on: ubuntu-24.04 needs: [run-tests] strategy: matrix: python-version: - 3.11 steps: - name: Checkout repo uses: actions/checkout@v6 - name: Setup Python ${{ matrix.python-version }} uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Download all artifacts uses: actions/download-artifact@v8 with: pattern: coverage-* merge-multiple: true path: reports - name: Install Python dependencies run: | pip install -r requirements/edx/coverage.txt - name: Run coverage run: | coverage combine reports/* coverage report coverage xml - uses: codecov/codecov-action@v5