.. _JOBTMPL/PublishCoverageResults:
.. index::
   single: CodeCov; PublishCoverageResults Template
   single: Codacy; PublishCoverageResults Template
   single: Coverage.py; PublishCoverageResults Template
   single: GitHub Action Reusable Workflow; PublishCoverageResults Template

PublishCoverageResults
######################

The ``PublishCoverageResults`` job template downloads artifacts provided by :ref:`JOBTMPL/UnitTesting` containing code
coverage databases created by :term:`Coverage.py`. These databases are then merged and converted into various output
formats like Cobertura XML, JSON or HTML. These outputs are either uploaded as a new artifact or can be published to
cloud services like :term:`CodeCov` or :term:`Codacy`.

.. topic:: Features

   * Merge SQLite code coverage databases generated by Coverage.py into a single
     SQLite database.
   * Convert SQLite database to Cobertura XML format.
   * Convert SQLite database to Coverage.py JSON format.
   * Convert SQLite database to HTML code coverage report.
   * Publish code coverage at CodeCov.
   * Publish code coverage as Codacy.

.. topic:: Behavior

   1. Checkout repository.
   2. Download artifact matching the :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_artifacts_pattern`.
   3. Install Python dependencies especially :pypi:`coverage`.
   4. Rename SQLite database files within artifact download directory to match the required filename pattern for
      Coverage.py's merge operation.
   5. Report code coverage as table into job log.
   6. Convert code coverage to Cobertura XML format.
   7. Convert code coverage to JSON format.
   8. Convert code coverage to HTML report (website).
   9. Upload merged SQLite database as artifact.
   10. Upload Cobertura XML file as artifact.
   11. Upload JSON file as artifact.
   12. Upload HTML report as artifact.
   13. Publish Cobertura report to CodeCov.
   14. Publish Cobertura report to Codacy.

.. topic:: Job Execution

   .. image:: ../../_static/pyTooling-Actions-PublishCoverageResults.png
      :width: 600px

.. topic:: Dependencies

   * :gh:`actions/checkout`
   * :gh:`pyTooling/download-artifact`

     * :gh:`actions/download-artifact`

   * pip

     * :pypi:`coverage`
     * :pypi:`tomli`

   * :gh:`pyTooling/upload-artifact`

     * :gh:`actions/upload-artifact`

   * :gh:`codecov/codecov-action`
   * :gh:`codacy/codacy-coverage-reporter-action`


.. _JOBTMPL/PublishCoverageResults/Instantiation:

Instantiation
*************

The following

.. code-block:: yaml

   jobs:
     ConfigParams:
       uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r6
       with:
         package_name: myPackage

     UnitTestingParams:
       uses: pyTooling/Actions/.github/workflows/Parameters.yml@r6
       with:
         package_name: myPackage

     UnitTesting:
       uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r6
       needs:
         - ConfigParams
         - UnitTestingParams
       with:
         jobs:                     ${{ needs.UnitTestingParams.outputs.python_jobs }}
         coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}

     PublishCoverageResults:
       uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r6
       needs:
         - ConfigParams
         - UnitTestingParams
         - UnitTesting
       with:
         coverage_report_json:   ${{ needs.ConfigParams.outputs.coverage_report_json }}
         coverage_report_html:   ${{ needs.ConfigParams.outputs.coverage_report_html }}
         coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
         coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
         codecov:                'true'
         codacy:                 'true'
       secrets:
         CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
         CODACY_TOKEN:  ${{ secrets.CODACY_TOKEN }}


.. _JOBTMPL/PublishCoverageResults/Parameters:

Parameter Summary
*****************

.. rubric:: Goto :ref:`input parameters <JOBTMPL/PublishCoverageResults/Inputs>`

+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| Parameter Name                                                              | Required | Type           | Default                                                                                                                  |
+=============================================================================+==========+================+==========================================================================================================================+
| :ref:`JOBTMPL/PublishCoverageResults/Input/ubuntu_image_version`            | no       | string         | ``'24.04'``                                                                                                              |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_artifacts_pattern`      | no       | string         | ``'*-CodeCoverage-SQLite-*'``                                                                                            |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_config`                 | no       | string         | ``'pyproject.toml'``                                                                                                     |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_xml`             | no       | string (JSON)  | :jsoncode:`{"directory": "report/coverage", "filename":  "coverage.xml", "fullpath":  "report/coverage/coverage.xml"}`   |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_json`            | no       | string (JSON)  | :jsoncode:`{"directory": "report/coverage", "filename":  "coverage.json", "fullpath":  "report/coverage/coverage.json"}` |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_html`            | no       | string (JSON)  | :jsoncode:`{"directory": "report/coverage/html"}`                                                                        |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_sqlite_artifact`        | no       | string         | ``''``                                                                                                                   |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_xml_artifact`           | no       | string         | ``''``                                                                                                                   |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_json_artifact`          | no       | string         | ``''``                                                                                                                   |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_html_artifact`          | no       | string         | ``''``                                                                                                                   |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/codecov`                         | no       | string         | ``'false'``                                                                                                              |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+
| :ref:`JOBTMPL/PublishCoverageResults/Input/codacy`                          | no       | string         | ``'false'``                                                                                                              |
+-----------------------------------------------------------------------------+----------+----------------+--------------------------------------------------------------------------------------------------------------------------+


.. rubric:: Goto :ref:`secrets <JOBTMPL/PublishCoverageResults/Secrets>`

+-----------------------------------------------------------+----------+----------+--------------+
| Token Name                                                | Required | Type     | Default      |
+===========================================================+==========+==========+==============+
| :ref:`JOBTMPL/PublishCoverageResults/Secret/CODECOV_TOKEN`| no       | string   | — — — —      |
+-----------------------------------------------------------+----------+----------+--------------+
| :ref:`JOBTMPL/PublishCoverageResults/Secret/CODACY_TOKEN` | no       | string   | — — — —      |
+-----------------------------------------------------------+----------+----------+--------------+

.. rubric:: Goto :ref:`output parameters <JOBTMPL/PublishCoverageResults/Outputs>`

This job template has no output parameters.


.. _JOBTMPL/PublishCoverageResults/Inputs:

Input Parameters
****************

.. _JOBTMPL/PublishCoverageResults/Input/ubuntu_image_version:

.. include:: ../_ubuntu_image_version.rst


.. _JOBTMPL/PublishCoverageResults/Input/coverage_artifacts_pattern:

coverage_artifacts_pattern
==========================

:Type:            string
:Required:        no
:Default Value:   ``'*-CodeCoverage-SQLite-*'``
:Possible Values: Any valid artifact matching pattern using fixed text and ``*`` characters.
:Description:     tbd


.. _JOBTMPL/PublishCoverageResults/Input/coverage_config:

coverage_config
===============

:Type:            string
:Required:        no
:Default Value:   ``'pyproject.toml'``
:Possible Values: Any valid path to a :file:`pyproject.toml` file. |br|
                  Alternatively, path to a :file:`.coveragerc` file (deprecated).
:Description:     Path to a Python project configuration file for extraction of project settings.
:Example:
                  .. grid:: 2

                     .. grid-item::
                        :columns: 5

                        .. rubric:: Extracted values from :file:`pyproject.toml`

                        .. code-block:: toml

                           [tool.pytest]
                           junit_xml = "report/unit/UnittestReportSummary.xml"

                           [tool.pyedaa-reports]
                           junit_xml = "report/unit/unittest.xml"

                           [tool.coverage.xml]
                           output = "report/coverage/coverage.xml"

                           [tool.coverage.json]
                           output = "report/coverage/coverage.json"

                           [tool.coverage.html]
                           directory = "report/coverage/html"
                           title="Code Coverage of pyDummy"


.. _JOBTMPL/PublishCoverageResults/Input/coverage_report_xml:

coverage_report_xml
===================

:Type:            string (JSON)
:Required:        no
:Default Value:
                  .. code-block:: json

                     { "directory": "reports/coverage",
                       "filename":  "coverage.xml",
                       "fullpath":  "reports/coverage/coverage.xml"
                     }
:Possible Values: Any valid JSON string containing a JSON object with fields:

                  :directory: Directory or sub-directory where the code coverage report in Cobertura XML format will be
                              saved.
                  :filename:  Filename of the generated Cobertura XML report. |br|
                              Any valid XML filename.
                  :fullpath:  The concatenation of both previous fields using the ``/`` separator.
:Description:     Directory, filename and fullpath as JSON object where the code coverage report in Cobertura XML format
                  will be saved. |br|
                  This path is configured in :file:`pyproject.toml` and can be extracted by
                  :ref:`JOBTMPL/ExtractConfiguration`.
:Example:
                  .. code-block:: yaml

                     ConfigParams:
                       uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r6

                     PublishCoverageResults:
                       uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r6
                       needs:
                         - ConfigParams
                       with:
                         ...
                         coverage_report_xml: ${{ needs.ConfigParams.outputs.coverage_report_xml }}


.. _JOBTMPL/PublishCoverageResults/Input/coverage_report_json:

coverage_report_json
====================

:Type:            string (JSON)
:Required:        no
:Default Value:
                  .. code-block:: json

                     { "directory": "reports/coverage",
                       "filename":  "coverage.json",
                       "fullpath":  "reports/coverage/coverage.json"
                     }
:Possible Values: Any valid JSON string containing a JSON object with fields:

                  :directory: Directory or sub-directory where the code coverage report in Coverage.py's JSON format
                              will be saved.
                  :filename:  Filename of the generated Coverage.py JSON report. |br|
                              Any valid JSON filename.
                  :fullpath:  The concatenation of both previous fields using the ``/`` separator.
:Description:     Directory, filename and fullpath as JSON object where the code coverage report in Coverage.py's JSON
                  format will be saved. |br|
                  This path is configured in :file:`pyproject.toml` and can be extracted by
                  :ref:`JOBTMPL/ExtractConfiguration`.
:Example:
                  .. code-block:: yaml

                     ConfigParams:
                       uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r6

                     PublishCoverageResults:
                       uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r6
                       needs:
                         - ConfigParams
                       with:
                         ...
                         coverage_report_json: ${{ needs.ConfigParams.outputs.coverage_report_json }}


.. _JOBTMPL/PublishCoverageResults/Input/coverage_report_html:

coverage_report_html
====================

:Type:            string (JSON)
:Required:        no
:Default Value:
                  .. code-block:: json

                     { "directory": "reports/coverage/html"
                     }
:Possible Values: Any valid JSON string containing a JSON object with fields:

                  :directory: Directory or sub-directory where the code coverage report in HTML format will be saved.
:Description:     Directory as JSON object where the code coverage report in HTML format will be saved. |br|
                  This path is configured in :file:`pyproject.toml` and can be extracted by
                  :ref:`JOBTMPL/ExtractConfiguration`.
:Example:
                  .. code-block:: yaml

                     ConfigParams:
                       uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r6

                     PublishCoverageResults:
                       uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r6
                       needs:
                         - ConfigParams
                       with:
                         ...
                         coverage_report_html: ${{ needs.ConfigParams.outputs.coverage_report_html }}


.. _JOBTMPL/PublishCoverageResults/Input/coverage_sqlite_artifact:

coverage_sqlite_artifact
========================

:Type:            string
:Required:        no
:Default Value:   ``''``
:Possible Values: Any valid artifact name.
:Description:     Name of the artifact containing the merged SQLite code coverage database.


.. _JOBTMPL/PublishCoverageResults/Input/coverage_xml_artifact:

coverage_xml_artifact
=====================

:Type:            string
:Required:        no
:Default Value:   ``''``
:Possible Values: Any valid artifact name.
:Description:     Name of the artifact containing the merged code coverage report as Cobertura XML file.


.. _JOBTMPL/PublishCoverageResults/Input/coverage_json_artifact:

coverage_json_artifact
======================

:Type:            string
:Required:        no
:Default Value:   ``''``
:Possible Values: Any valid artifact name.
:Description:     Name of the artifact containing the merged code coverage report as Coverage.py JSON file.


.. _JOBTMPL/PublishCoverageResults/Input/coverage_html_artifact:

coverage_html_artifact
======================

:Type:            string
:Required:        no
:Default Value:   ``'report/coverage/html'``
:Possible Values: Any valid artifact name.
:Description:     Name of the artifact containing the merged code coverage report as HTML report.


.. _JOBTMPL/PublishCoverageResults/Input/codecov:

codecov
=======

:Type:            string
:Required:        no
:Default Value:   ``'false'``
:Possible Values: ``'true'``, ``'false'``
:Description:     If *true*, publish code coverage results to CodeCov.


.. _JOBTMPL/PublishCoverageResults/Input/codacy:

codacy
======

:Type:            string
:Required:        no
:Default Value:   ``'false'``
:Possible Values: ``'true'``, ``'false'``
:Description:     If *true*, publish code coverage results to Codacy.


.. _JOBTMPL/PublishCoverageResults/Secrets:

Secrets
*******

The workflow template uses the following secrets to publish results to other services.

.. _JOBTMPL/PublishCoverageResults/Secret/CODECOV_TOKEN:

CODECOV_TOKEN
=============

:Type:            string
:Required:        no
:Default Value:   — — — —
:Description:     The token to publish code coverage and unit test results to :term:`CodeCov`.


.. _JOBTMPL/PublishCoverageResults/Secret/CODACY_TOKEN:

CODACY_TOKEN
============

:Type:            string
:Required:        no
:Default Value:   — — — —
:Description:     The token to publish code coverage results to :term:`Codacy`.



.. _JOBTMPL/PublishCoverageResults/Outputs:

Outputs
*******

The following optimizations can be used to reduce the template's runtime.

Disable code coverage SQLite database artifact upload
  If parameter :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_sqlite_artifact` is empty, the collected code coverage database
  (SQLlite format) wont be uploaded as an artifact.
Disable code coverage report conversion to the Cobertura XML format.
  If parameter :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_xml_artifact` is empty, no Cobertura XML file will be generated
  from code coverage report. As no Cobertura XML file exists, no code coverage XML artifact will be uploaded.
Disable code coverage report conversion to the *Coverage.py* JSON format.
  If parameter :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_json_artifact` is empty, no *Coverage.py* JSON file will be
  generated from code coverage report. As no JSON file exists, no code coverage JSON artifact will be uploaded.
Disable code coverage report conversion to an HTML website.
  If parameter :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_html_artifact` is empty, no coverage report HTML report will be
  generated from code coverage report. As no HTML report exists, no code coverage HTML artifact will be uploaded.

.. todo:: PublishCoverageResults:: Disable publishing to codecov and codacy. |br| If upload is enabled, XML will be always generated.
