diff --git a/.github/workflows/README.md b/.github/workflows/README.md index ca5de021704..aa8fd99d3e8 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -69,5 +69,17 @@ Documentation for used GitHub secrets. + + COVERAGE_SCRIPT_CLONE + Yes + + Github Deploy token linked to the [development repo](https://github.com/specify/specify-development) to allow actions to clone it. + + + + #8278 + + + diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml new file mode 100644 index 00000000000..7b358ba6250 --- /dev/null +++ b/.github/workflows/coverage.yml @@ -0,0 +1,168 @@ +name: Coverage + +on: + pull_request: + push: + workflow_dispatch: + +jobs: + # copied from test.yml + changes: + name: Check if back-end or front-end files changed + # Don't run this for pushes generated by push.yml on weblate-localization + # branch → prevents an infinite loop of actions triggering actions + # + # Also, "push" event is not triggered for forks, so need to listen for + # pull_requests, but only for external ones, so as not to run the action + # twice + if: | + (github.event_name == 'workflow_dispatch' || + (github.event.head_commit.committer.name != 'Hosted Weblate' && + github.event.head_commit.committer.name != 'github-actions')) + && + ( + github.event_name != 'pull_request' || + github.event.pull_request.head.repo.fork == true + ) + runs-on: ubuntu-latest + outputs: + backend_changed: ${{ steps.back-end-check.outputs.changed }} + frontend: ${{ steps.filter.outputs.frontend }} + frontend_changes: ${{ steps.filter.outputs.frontend_files }} + + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Find all changed files + uses: dorny/paths-filter@v3 + id: filter + with: + base: ${{ github.ref }} + list-files: escape + filters: | + frontend: + - 'specifyweb/frontend/**' + backend: + - '**' + + - name: Check if any non-front-end files changed + id: back-end-check + run: | + changed_files=`echo "${{steps.filter.outputs.backend_files}}" | tr " " "\n" | grep -v 'specifyweb/frontend/' || echo ""` + echo "Changed back-end files: ${changed_files}" + echo "changed=$([[ -z "${changed_files}" ]] && echo "" || echo "1")" >> $GITHUB_OUTPUT + + setup-and-run: + needs: changes + if: | + (needs.changes.outputs.backend_changed || + needs.changes.outputs.frontend) || + github.event_name == 'workflow_dispatch' + runs-on: ubuntu-latest + + + steps: + - name: Install needed packages + id: apt + run: | + sudo apt update + sudo apt install docker-compose-v2 openssh-client + + - uses: actions/checkout@v4 + with: + persist-credentials: false + + - name: Fetch coverage script + id: clone-coverage + run: | + eval "$(ssh-agent -s)" + ssh-add - <<< '${{ secrets.COVERAGE_SCRIPT_CLONE }}' + cd ~ + git clone git@github.com:specify/specify-development + sudo install -m 0777 -o "$USER" specify-development/scripts/tests/{run-coverage,test_coverage.py} /usr/bin/ + cd - + + - name: Configure specify + id: config-specify + run: | + cat > .env <<-EOS + DATABASE_HOST=mariadb + DATABASE_PORT=3306 + MYSQL_ROOT_PASSWORD=password + DATABASE_NAME=specify + + MASTER_NAME=root + MASTER_PASSWORD=password + MASTER_HOST=% + + MIGRATOR_NAME=root + MIGRATOR_PASSWORD=password + MIGRATOR_HOST=% + + APP_USER_NAME=root + APP_USER_PASSWORD=password + APP_HOST=% + + ALLOW_SUPPORT_LOGIN=false + SUPPORT_LOGIN_TTL=180 + + SECRET_KEY=change_this_to_some_unique_random_string + + ASSET_SERVER_URL=http://host.docker.internal/web_asset_store.xml + ASSET_SERVER_KEY=your_asset_server_access_key + REDIS_HOST=redis + REDIS_PORT=6379 + REDIS_DB_INDEX=0 + + REPORT_RUNNER_HOST=report-runner + REPORT_RUNNER_PORT=8080 + + CELERY_BROKER_URL=redis://redis/0 + CELERY_RESULT_BACKEND=redis://redis/1 + + TIME_ZONE=America/Chicago + + LOG_LEVEL=WARNING + + SP7_DEBUG=true + EOS + + sed -i 's/#[ ]*\(.*requirements-testing.txt\)/\1/; s/\(COPY\) \(requirements-testing.txt\)/\1 --chown=specify:specify \2/' Dockerfile + sed -i 's/\(\(DATABASE_\|MASTER_\|MIGRATOR\|APP_USER_\)[^O].*\) = \(.*\)/\1 = os.environ.get("\1", "")/' specifyweb/settings/specify_settings.py + for i in range {0..3}; do + sudo chmod a+x $(find . -type d) + sudo chmod -R a+rw . + done + docker compose up --build -d + + - name: Fix mariadb + id: reboot-mariadb + run: | + sleep 10 + docker compose up -d mariadb + sleep 10 + docker exec mariadb mariadb -uroot -ppassword -e"DROP USER root; + CREATE USER 'root'@'%' IDENTIFIED BY 'password'; + GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY 'password'; + DROP DATABASE IF EXISTS specify;" + docker compose down + docker compose up -d + sleep 10 + + + - name: Run the script + id: run-coverage + run: run-coverage -t pj -a pj -d pj -o html,csv + + + - name: Upload report as artifact + uses: actions/upload-artifact@v7 + with: + name: coverage-report + path: ./report.tar.bz2 + archive: false + retention-days: 1 + + diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 00000000000..c5c37d97a12 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +DJANGO_SETTINGS_MODULE = specifyweb.settings diff --git a/requirements-testing.txt b/requirements-testing.txt index 21bba85648c..aab161ee7f1 100644 --- a/requirements-testing.txt +++ b/requirements-testing.txt @@ -3,4 +3,6 @@ mypy==1.5.1 hypothesis>=6.131.9,<7 hypothesis-jsonschema==0.19.0 types-requests==2.28.5 -lxml \ No newline at end of file +lxml +coverage +pytest-django