{"id":11740133,"name":"lfreleng-actions/python-test-action","ecosystem":"actions","description":"Test a Python Project, generate coverage report","homepage":"","licenses":"other","normalized_licenses":["GPL-1.0+"],"repository_url":"https://github.com/lfreleng-actions/python-test-action","keywords_array":["github-actions","pytest","python","test","testing","tests"],"namespace":"lfreleng-actions","versions_count":13,"first_release_published_at":"2025-03-28T16:19:46.000Z","latest_release_published_at":"2025-10-07T12:37:33.000Z","latest_release_number":"v0.1.12","last_synced_at":"2026-03-18T09:42:36.839Z","created_at":"2025-06-06T18:53:46.688Z","updated_at":"2026-03-18T09:42:36.839Z","registry_url":"https://github.com/lfreleng-actions/python-test-action","install_command":null,"documentation_url":null,"metadata":{"name":"🧪 Python Test","description":"Test a Python Project, generate coverage report","inputs":{"python_version":{"description":"Python version used to run test","required":true},"permit_fail":{"description":"Continue even when one or more tests fails","required":false,"default":"false"},"report_artefact":{"description":"Uploads test/coverage report bundle as artefact","required":false,"default":"true"},"path_prefix":{"description":"Directory location containing Python project code","required":false,"default":"."},"tests_path":{"description":"Path relative to the project folder containing tests","required":false},"tox_tests":{"description":"Uses tox to perform tests","required":false,"default":"false"},"tox_envs":{"description":"Space separated list of tox environments to run","required":false},"github_token":{"description":"GitHub token for API access during tests","required":false}},"runs":{"using":"composite","steps":[{"name":"Setup action/environment","shell":"bash","env":{"GITHUB_TOKEN":"${{ inputs.github_token }}"},"run":"# Setup action/environment\nif [ -z \"${{ inputs.python_version }}\" ]; then\n  echo 'Error: Python version was not provided ❌'; exit 1\nelse\n  echo \"Using Python: ${{ inputs.python_version }} 🐍\"\nfi\n\n# Verify path_prefix is a valid directory path\nif [ ! -d \"${{ inputs.path_prefix }}\" ]; then\n  echo 'Error: invalid path/prefix to project directory ❌'; exit 1\nfi\n\n# The coverage report location will also use this environment variable\ntox_envs=$(echo \"py${{ inputs.python_version }}\" | sed 's/\\.//g')\necho \"tox_envs=$tox_envs\" \u003e\u003e \"$GITHUB_ENV\"\n\n# Setup dedicated coverage report directory outside project path\ncoverage_dir=\"/tmp/coverage-$tox_envs\"\nmkdir -p \"$coverage_dir\"\necho \"coverage_dir=$coverage_dir\" \u003e\u003e \"$GITHUB_ENV\"\necho \"Coverage report output location: $coverage_dir 💬\"\n\nif [ \"f${{ inputs.permit_fail }}\" = 'ftrue' ]; then\n  echo 'Warning: test failures will be permitted ⚠️'\nfi\n\n# Testing with TOX\nif [ \"f${{ inputs.tox_tests }}\" = 'ftrue' ]; then\n  echo 'Using tox to perform tests 💬'\n  if [ -z \"${{ inputs.tox_envs }}\" ]; then\n    echo 'Using tox environment derived from matrix Python version'\n    echo \"Using current matrix python version: $tox_envs\"\n  else\n    tox_envs=\"${{ inputs.tox_envs }}\"\n    echo \"Testing with tox environments: ${{ inputs.tox_envs }} 💬\"\n  fi\n  echo \"tox_envs=$tox_envs\" \u003e\u003e \"$GITHUB_ENV\"\nfi\n\n# Check/setup test path\nif [ -n \"${{ inputs.tests_path }}\" ] \u0026\u0026 \\\n  [ ! -d \"${{ inputs.path_prefix }}/${{ inputs.tests_path }}\" ]; then\n  echo 'Error: invalid path/prefix to test directory ❌'\n  echo \"${{ inputs.path_prefix }}/${{ inputs.tests_path }}\"; exit 1\nfi\nif [ -n \"${{ inputs.tests_path }}\" ]; then\n  TESTS_PATH=\"${{ inputs.path_prefix }}/${{ inputs.tests_path }}\"\n# Otherwise search/use common locations\nelif [ -d \"${{ inputs.path_prefix }}/test\" ]; then\n  TESTS_PATH=\"${{ inputs.path_prefix }}/test\"\nelif [ -d \"${{ inputs.path_prefix }}/tests\" ]; then\n  TESTS_PATH=\"${{ inputs.path_prefix }}/tests\"\nelse\n  echo 'Error: could not determine path to tests ❌'; exit 1\nfi\necho \"Tests path: $TESTS_PATH 💬\"\necho \"tests_path=$TESTS_PATH\" \u003e\u003e \"$GITHUB_ENV\"\n"},{"name":"Check for data_file in pyproject.toml","uses":"lfreleng-actions/file-grep-regex-action@64fbf6bd3315530c6819e16c5b065e3bfc4f16d9","id":"cov-run","with":{"flags":"-E","regex":"^data_file\\s*=.*","filename":"${{ inputs.path_prefix }}/pyproject.toml","no_fail":"true"}},{"name":"Warning: coverage temporary files","if":"steps.cov-run.outputs.extracted_string == ''","shell":"bash","run":"# Warning: coverage temporary files\necho \"Warning: coverage report temporary files ⚠️\"\necho \"Tests sensitive to file system content may break\"\necho \"Set data_file parameter in pyproject.toml to avoid this warning\"\n"},{"name":"Check for tox configuration file","if":"inputs.tox_tests == 'true'","id":"tox-config","uses":"lfreleng-actions/path-check-action@aa7dabfa92e50e31a0f091dd3e2741692e8dde07","with":{"path":"${{ inputs.path_prefix }}/tox.ini"}},{"name":"Tox configuration file missing","if":"steps.tox-config.outputs.type != 'file' \u0026\u0026 inputs.tox_tests == 'true'","shell":"bash","run":"# Tox configuration file missing\necho 'Error: tox configuration file missing ❌'; exit 1\n"},{"name":"Set up Python ${{ inputs.python_version }}","uses":"actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c","with":{"python-version":"${{ inputs.python_version }}"}},{"name":"Cache Python dependencies","uses":"actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830","with":{"path":"~/.cache/pip\n~/.cache/pypoetry\n~/.cache/pipenv\n.venv\n.tox\n","key":"python-${{ runner.os }}-${{ inputs.python_version }}- ${{ hashFiles('**/requirements*.txt', '**/pyproject.toml', '**/poetry.lock', '**/Pipfile*', '**/setup.py', '**/setup.cfg') }}","restore-keys":"python-${{ runner.os }}-${{ inputs.python_version }}-\npython-${{ runner.os }}-\n"}},{"name":"Performing tests [tox]","if":"steps.tox-config.outputs.type == 'file' \u0026\u0026 inputs.tox_tests == 'true'","shell":"bash","env":{"GITHUB_TOKEN":"${{ inputs.github_token }}"},"run":"# Performing tests [tox]\necho 'Installing: tox ⬇️'\n# Under Python 3.8, use a compatible tox release, latest for others\nif [[ \"${{ inputs.python_version }}\" == \"3.8\" ]]; then\n  echo 'Using tox\u003c4.0.0 for Python 3.8 compatibility'\n  pip install --disable-pip-version-check -q 'tox\u003c4.0.0'\nelse\n  echo 'Using latest tox version'\n  pip install --disable-pip-version-check -q tox\nfi\nif [ -n \"${{ env.tox_envs }}\" ]; then\n  for ENV in \"${{ env.tox_envs }}\"; do\n    echo \"Running: tox -c ${{ inputs.path_prefix }}/tox.ini -e $ENV 💬\"\n    tox -c \"${{ inputs.path_prefix }}/tox.ini\" -e \"$ENV\"\n  done\nelse\n  echo 'Running: tox -c ${{ inputs.path_prefix }}/tox.ini 💬'\n  tox -c \"${{ inputs.path_prefix }}/tox.ini\"\nfi\n"},{"name":"Install project and test/dev dependencies [pytest]","if":"inputs.tox_tests != 'true'","shell":"bash","env":{"GITHUB_TOKEN":"${{ inputs.github_token }}"},"run":"# Install project and test/dev dependencies\n\n# Important note: package installation order matters\n# Install the package (editable or not) before installing test runners\n# (like pytest and coverage) to ensure the latest code is used\necho 'Install project and test/dev dependencies (before pytest install)'\nif [ -f \"${{ inputs.path_prefix }}/pyproject.toml\" ]; then\n  echo \"Source: ${{ inputs.path_prefix }}/pyproject.toml ⬇️\"\n  # First try to install with test dependencies\n  if pip install -e \"${{ inputs.path_prefix }}[test,dev]\"; then\n    echo 'Successfully installed test and dev dependencies ✅'\n  elif pip install -e \"${{ inputs.path_prefix }}[test]\"; then\n    echo 'Successfully installed test dependencies ✅'\n  else\n    echo 'Fallback: installing base package only ⚠️'\n    pip install -e \"${{ inputs.path_prefix }}\"\n  fi\nelif [ -f \"${{ inputs.path_prefix }}/requirements.txt\" ]; then\n  echo \"Source: ${{ inputs.path_prefix }}/requirements.txt ⬇️\"\n  pip install -r \"${{ inputs.path_prefix }}/requirements.txt\"\nfi\n\necho 'Installing: pytest, pytest-cov, coverage[toml] ⬇️'\npip install --disable-pip-version-check -q \\\n  pytest \\\n  pytest-cov \\\n  coverage\\[toml\\]\n"},{"name":"Run tests and coverage report [pytest]","if":"inputs.tox_tests != 'true'","shell":"bash","env":{"GITHUB_TOKEN":"${{ inputs.github_token }}"},"run":"# Tests and coverage report [pytest]\n\n# Setup XML coverage report for upload as artefact\nif [ ${{ inputs.report_artefact }} = 'true' ]; then\n  coverage_flags=\"--cov-report=term-missing \\\n  --cov-report=xml:/tmp/coverage-$tox_envs/coverage.xml \\\n  --cov-config=${{ inputs.path_prefix }}/pyproject.toml\"\nfi\n\necho \"Running tests in: ${{ env.tests_path }} 🧪\"\nif [ \"f${{ inputs.permit_fail }}\" = 'ftrue' ]; then\n  echo 'Warning: flag set to permit test failures ⚠️'\n  pytest \\\n    $coverage_flags \\\n    ${{ env.tests_path }} || true\nelse\n  pytest \\\n    $coverage_flags \\\n    ${{ env.tests_path }}\nfi\n"},{"name":"Upload test/coverage report","uses":"actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02","if":"inputs.report_artefact == 'true'","with":{"name":"${{ env.tox_envs }}-coverage.xml","path":"${{ env.coverage_dir }}/coverage.xml","retention-days":90}}]},"default_branch":"main","path":null},"repo_metadata":{"id":284962404,"uuid":"954829781","full_name":"lfreleng-actions/python-test-action","owner":"lfreleng-actions","description":"Tests a Python project and generates coverage reports","archived":false,"fork":false,"pushed_at":"2025-10-20T20:27:47.000Z","size":174,"stargazers_count":0,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-20T22:27:38.804Z","etag":null,"topics":["github-actions","pytest","python","test","testing","tests"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lfreleng-actions.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-03-25T17:19:54.000Z","updated_at":"2025-10-15T12:30:43.000Z","dependencies_parsed_at":"2025-05-26T13:43:41.816Z","dependency_job_id":"7d307a0f-5ae1-4f5f-9b8a-2ae0519d06fa","html_url":"https://github.com/lfreleng-actions/python-test-action","commit_stats":null,"previous_names":["lfreleng-actions/python-test-action"],"tags_count":13,"template":false,"template_full_name":"lfreleng-actions/actions-template","purl":"pkg:github/lfreleng-actions/python-test-action","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfreleng-actions%2Fpython-test-action","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfreleng-actions%2Fpython-test-action/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfreleng-actions%2Fpython-test-action/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfreleng-actions%2Fpython-test-action/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lfreleng-actions","download_url":"https://codeload.github.com/lfreleng-actions/python-test-action/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfreleng-actions%2Fpython-test-action/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280552129,"owners_count":26349694,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-23T02:00:06.710Z","response_time":142,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"},"tags":[]},"repo_metadata_updated_at":"2025-10-23T03:12:13.611Z","dependent_packages_count":0,"downloads":null,"downloads_period":null,"dependent_repos_count":0,"rankings":{"downloads":null,"dependent_repos_count":34.69762145748988,"dependent_packages_count":0.0,"stargazers_count":null,"forks_count":null,"docker_downloads_count":null,"average":17.34881072874494},"purl":"pkg:githubactions/lfreleng-actions/python-test-action","advisories":[],"docker_usage_url":"https://docker.ecosyste.ms/usage/actions/lfreleng-actions/python-test-action","docker_dependents_count":null,"docker_downloads_count":null,"usage_url":"https://repos.ecosyste.ms/usage/actions/lfreleng-actions/python-test-action","dependent_repositories_url":"https://repos.ecosyste.ms/api/v1/usage/actions/lfreleng-actions/python-test-action/dependencies","status":null,"funding_links":[],"critical":null,"issue_metadata":{"last_synced_at":"2025-10-20T23:05:35.540Z","issues_count":1,"pull_requests_count":81,"avg_time_to_close_issue":null,"avg_time_to_close_pull_request":100168.8,"issues_closed_count":0,"pull_requests_closed_count":70,"pull_request_authors_count":3,"issue_authors_count":1,"avg_comments_per_issue":0.0,"avg_comments_per_pull_request":0.1728395061728395,"merged_pull_requests_count":68,"bot_issues_count":1,"bot_pull_requests_count":63,"past_year_issues_count":1,"past_year_pull_requests_count":81,"past_year_avg_time_to_close_issue":null,"past_year_avg_time_to_close_pull_request":100168.8,"past_year_issues_closed_count":0,"past_year_pull_requests_closed_count":70,"past_year_pull_request_authors_count":3,"past_year_issue_authors_count":1,"past_year_avg_comments_per_issue":0.0,"past_year_avg_comments_per_pull_request":0.1728395061728395,"past_year_bot_issues_count":1,"past_year_bot_pull_requests_count":63,"past_year_merged_pull_requests_count":68,"issues_url":"https://issues.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfreleng-actions%2Fpython-test-action/issues","maintainers":[],"active_maintainers":[]},"versions_url":"https://packages.ecosyste.ms/api/v1/registries/github%20actions/packages/lfreleng-actions%2Fpython-test-action/versions","version_numbers_url":"https://packages.ecosyste.ms/api/v1/registries/github%20actions/packages/lfreleng-actions%2Fpython-test-action/version_numbers","dependent_packages_url":"https://packages.ecosyste.ms/api/v1/registries/github%20actions/packages/lfreleng-actions%2Fpython-test-action/dependent_packages","related_packages_url":"https://packages.ecosyste.ms/api/v1/registries/github%20actions/packages/lfreleng-actions%2Fpython-test-action/related_packages","codemeta_url":"https://packages.ecosyste.ms/api/v1/registries/github%20actions/packages/lfreleng-actions%2Fpython-test-action/codemeta","maintainers":[]}