Skip to content

Update setup-python to v5 to use Node 20 #35

Update setup-python to v5 to use Node 20

Update setup-python to v5 to use Node 20 #35

Workflow file for this run

name: Python CI
on:
# Enables trigger for commits or PRs when making changes to python namespaces.
push:
branches: [main]
pull_request:
types: [opened, synchronize]
paths:
# Python namespaces
- 'ci/**/*.py'
- 'ocebuild/**/*.py'
# Python configuration
- 'poetry.lock'
- 'pyproject.toml'
workflow_dispatch:
env:
poetry-version: 1.5.0
jobs:
# Runs test suite
tests:
runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }}
strategy:
fail-fast: false
matrix:
include:
# Legacy versions
# @see https://endoflife.date/python
- python-version: "3.8"
experimental: false
# Stable versions
- python-version: "3.9"
experimental: false
- python-version: "3.10"
experimental: false
- python-version: "3.11"
experimental: false
- python-version: "3.12"
experimental: false
# Experimental versions
# @see https://raw.githubusercontent.com/actions/python-versions/main/versions-manifest.json
# - python-version: "3.13-dev"
# python-min-version: "3.13.0rc1"
# experimental: true
# os: [ubuntu-latest, windows-latest, macos-latest]
name: "Test (python ${{ matrix.python-version }})"
steps:
# Fetches remote repository without --progress option.
#
# The default behavior of @actions/checkout outputs many noisy lines of
# status output in the workflow log, which is problematic for log size.
- name: Checkout latest repository commit
uses: actions/checkout@v4
with:
show-progress: false
# Setup python virtual environment
- name: Install poetry
run: pipx install poetry==${{ env.poetry-version }}
- name: Setup Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: poetry
cache-dependency-path: poetry.lock
- name: Install python dev dependencies
run: |
pip3 install packaging \
--ignore-installed
# Verify installed python version in poetry virtualenv
- name: Validate experimental python versions
id: validate-experimental
if: ${{ matrix.experimental }}
continue-on-error: true
run: |
# Exists with exit code 1 if not within specified range
python3 ci/scripts/compare_version.py \
--min "${{ matrix.python-min-version }}" \
--max "${{ matrix.python-max-version }}"
# Setup Poetry virtual environment
- name: Use matrix python version in Poetry virtualenv
run: |
poetry env use ${{ matrix.python-version }}
- name: Setup Poetry plugins and project dependencies
run: poetry install -n
# Check the current runner environment
- name: Check GitHub API limit
if: steps.validate-experimental.outcome != 'failure'
continue-on-error: ${{ matrix.experimental }}
run: poetry run python3 ci/scripts/lib/rate-limit.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Run test suites
- name: Run test suite
id: python-pytest
if: steps.validate-experimental.outcome != 'failure'
continue-on-error: ${{ matrix.experimental }}
run: |
poetry test -vvv
env:
COVERAGE_FILE: ".coverage.${{ matrix.python-version }}"
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Upload coverage data
- name: Store coverage file
if: steps.python-pytest.outcome != 'failure'
uses: actions/upload-artifact@v3
with:
name: coverage
path: .coverage.${{ matrix.python-version }}
# Verify python matrix results for branch protection
# @see https://github.com/orgs/community/discussions/33579#discussioncomment-3796858
check:
name: Validating test runs (python >=3.8,<3.12)
if: always()
needs:
- tests
runs-on: ubuntu-latest
permissions:
statuses: write
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@release/v1
with:
jobs: ${{ toJSON(needs) }}
# - name: Set final commit status
# run: |
# curl --request POST \
# --url https://api.github.com/repos/${{ github.repository }}/statuses/${{ github.event.pull_request.head.sha || github.sha }} \
# --header 'authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' \
# --header 'content-type: application/json' \
# --data '{
# "state": "${{ job.status }}",
# "description": "Updated status to reflect required python tests.",
# "context": "ci:python"
# }'
# Generate coverage branch data and PR comment text
#
# Updates `python-coverage-comment-action` branch
# and edits cached PR comment text reporting test coverage.
coverage-branch:
name: Coverage (python >=3.8)
runs-on: ubuntu-latest
needs: tests
permissions:
pull-requests: write
contents: write
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
id: download
with:
name: 'coverage'
- name: Coverage comment
id: coverage_comment
uses: py-cov-action/python-coverage-comment-action@v3
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# If true, will run `coverage combine` before reading the `.coverage` file.
MERGE_COVERAGE_FILES: true
# If true, will create an annotation on every line with missing coverage on a pull request.
ANNOTATE_MISSING_LINES: false
# Only needed if ANNOTATE_MISSING_LINES is set to true. This parameter allows you to choose between
# notice, warning and error as annotation type. For more information look here:
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message
ANNOTATION_TYPE: warning
# An alternative template for the comment for pull requests.
COMMENT_TEMPLATE: |
### Python Coverage: `{{ coverage.info.percent_covered | pct }}`
Line Coverage Summary:
| (Files) | Diff (Changed Lines) | Covered Lines | Missing Lines | Excluded Lines | (Total) |
| ------------------------------------------ | ------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| {{ diff_coverage.files.items() | length }} | {{ diff_coverage.num_changed_lines }} | {{ coverage.info.covered_lines }} ({{ (coverage.info.covered_lines|int / coverage.info.num_statements|int) | pct }}) | {{ coverage.info.missing_lines }} ({{ (coverage.info.missing_lines|int / coverage.info.num_statements|int) | pct }}) | {{ coverage.info.excluded_lines }} ({{ (coverage.info.excluded_lines|int / coverage.info.num_statements|int) | pct }}) | {{ coverage.info.num_statements }} |
{%if diff_coverage.files -%}
<details>
<summary>Diff Coverage Details (click to unfold)</summary>
| (#) | File (^Test) | Diff (%) | Covered Lines | Missing Lines | Excluded Lines | (Total) |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
{% for filename, diff_file_coverage in diff_coverage.files | dictsort -%}
{%- set list=diff_file_coverage.violation_lines -%}
{%- set stack={ 'first': None, 'last': None, 'pending': None } -%}
{%- set output=[] -%}
{%- for line in list -%}
{%- if loop.index0 and line == list[loop.index0-1] + 1 -%}
{{ stack.update({ 'last': line }) or "" }}
{%- set range = stack.first ~ '-' ~ stack.last -%}
{{ stack.update({ 'pending': ('#L' ~ range | replace("-", "-L")) }) or "" }}
{%- else -%}
{{ stack.update({ 'first': line, 'last': None, 'pending': '#L' ~ line }) or "" }}
{%- endif -%}
{%- if (line+1 != list[loop.index]) -%}
{{ output.append(stack['pending']) or "" }}
{%- endif -%}
{%- endfor -%}
| {{ loop.index }} | [`{{ filename | replace("ocebuild/", "", 1) }}`](https://github.com/${{github.repository}}/blob/${{github.head_ref}}/{{ filename }}) ([^](https://github.com/${{github.repository}}/blob/${{github.head_ref}}/{{ filename | replace(".py", "_test.py", 1) }})) | {{ "%+.0f" | format((coverage.files[filename].info.percent_covered - diff_file_coverage.percent_covered) | round | float) }}% | {{ coverage.files[filename].info.covered_lines }} ({{ coverage.files[filename].info.percent_covered | float | pct }}) | {%- if diff_file_coverage.violation_lines -%}<details><summary>{{ diff_file_coverage.violation_lines | count }} ({{ ((diff_file_coverage.violation_lines | count) / coverage.files[filename].info.num_statements) | float | pct }})</summary>{% set separator = joiner(", ") %}{% for range in output %}{{ separator() }}[`{{ range | replace('L','') | replace('#','') }}`](https://github.com/${{github.repository}}/blob/${{github.head_ref}}/{{ filename ~ range }}){% endfor %}</details>{%- else -%}`None`{%- endif %} | {{ coverage.files[filename].info.excluded_lines }} ({{ (coverage.files[filename].info.excluded_lines / coverage.files[filename].info.num_statements) | float | pct }}) | {{ coverage.files[filename].info.num_statements }} |
{% endfor -%}
</details>
{%- endif %}
Last updated: `{{ coverage.meta.timestamp }}`
{{ marker }}
- name: Store Pull Request comment to be posted
uses: actions/upload-artifact@v3
if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
with:
name: python-coverage-comment-action
path: python-coverage-comment-action.txt