diff --git a/.github/workflows/ApplicationTesting.yml b/.github/workflows/ApplicationTesting.yml index 3baec2d..1c3ef4d 100644 --- a/.github/workflows/ApplicationTesting.yml +++ b/.github/workflows/ApplicationTesting.yml @@ -94,6 +94,7 @@ jobs: name: ${{ inputs.wheel }} path: install + # TODO: extract step to an Action so package lists are shared with UnitTesting (and GHDL?) - name: Compute pacman/pacboy packages id: pacboy if: matrix.system == 'msys2' diff --git a/.github/workflows/PublishCoverageResults.yml b/.github/workflows/PublishCoverageResults.yml index 281768d..d782f39 100644 --- a/.github/workflows/PublishCoverageResults.yml +++ b/.github/workflows/PublishCoverageResults.yml @@ -138,22 +138,22 @@ jobs: run: coverage combine --data-file=.coverage coverage/ - name: Report code coverage - run: coverage report --rcfile=pyproject.toml --data-file=.coverage + run: coverage report --rcfile=${{ inputs.coverage_config }} --data-file=.coverage - name: Convert to XML format (Cobertura) if: inputs.coverage_xml_artifact != '' || inputs.codecov || inputs.codacy - run: coverage xml --data-file=.coverage + run: coverage xml --rcfile=${{ inputs.coverage_config }} --data-file=.coverage - name: Convert to JSON format if: inputs.coverage_json_artifact != '' - run: coverage json --data-file=.coverage + run: coverage json --rcfile=${{ inputs.coverage_config }} --data-file=.coverage - name: Convert to HTML format if: inputs.coverage_html_artifact != '' run: | - coverage html --data-file=.coverage -d report/coverage/html - rm report/coverage/html/.gitignore - tree -pash report/coverage/html + coverage html --rcfile=${{ inputs.coverage_config }} --data-file=.coverage + rm ${{ inputs.coverage_report_html_directory }}/.gitignore + tree -pash ${{ inputs.coverage_report_html_directory }} - name: 📤 Upload 'Coverage SQLite Database' artifact uses: pyTooling/upload-artifact@v4 diff --git a/doc/JobTemplate/AllInOne/CompletePipeline.rst b/doc/JobTemplate/AllInOne/CompletePipeline.rst index acbb949..03fa0f5 100644 --- a/doc/JobTemplate/AllInOne/CompletePipeline.rst +++ b/doc/JobTemplate/AllInOne/CompletePipeline.rst @@ -214,7 +214,41 @@ It can be used for simple Python packages as well as namespace packages. * :pypi:`wheel` * :ref:`pyTooling/Actions/.github/workflows/PublishTestResults.yml ` + + * :gh:`actions/checkout` + * :gh:`pyTooling/download-artifact` + + * :gh:`actions/download-artifact` + + * pip + + * :pypi:`pyEDAA.Reports` + + * :gh:`dorny/test-reporter` + * :gh:`codecov/test-results-action` + * :gh:`pyTooling/upload-artifact` + + * :gh:`actions/upload-artifact` + * :ref:`pyTooling/Actions/.github/workflows/PublishCoverageResults.yml ` + + * :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` + * :ref:`pyTooling/Actions/.github/workflows/SphinxDocumentation.yml ` * :gh:`actions/checkout` @@ -252,6 +286,18 @@ It can be used for simple Python packages as well as namespace packages. * :ref:`pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml ` * :ref:`pyTooling/Actions/.github/workflows/PublishOnPyPI.yml ` + + * :gh:`pyTooling/download-artifact` + + * :gh:`actions/download-artifact` + * :gh:`actions/setup-python` + * :gh:`geekyeggo/delete-artifact` + + * pip + + * :pypi:`wheel` + * :pypi:`twine` + * :ref:`pyTooling/Actions/.github/workflows/TagReleaseCommit.yml ` * :gh:`actions/github-script` diff --git a/doc/JobTemplate/Documentation/LaTeXDocumentation.rst b/doc/JobTemplate/Documentation/LaTeXDocumentation.rst index 47b344e..c0e4187 100644 --- a/doc/JobTemplate/Documentation/LaTeXDocumentation.rst +++ b/doc/JobTemplate/Documentation/LaTeXDocumentation.rst @@ -131,7 +131,7 @@ latex_artifact :Required: yes :Default Value: — — — — :Possible Values: Any valid artifact name. -:Description: name of the artifact containing the LaTeX document to translate. +:Description: Name of the artifact containing the LaTeX document to translate. .. _JOBTMPL/LatexDocumentation/Input/document: diff --git a/doc/JobTemplate/Publish/PublishCoverageResults.rst b/doc/JobTemplate/Publish/PublishCoverageResults.rst index dd711ca..80afeb9 100644 --- a/doc/JobTemplate/Publish/PublishCoverageResults.rst +++ b/doc/JobTemplate/Publish/PublishCoverageResults.rst @@ -3,20 +3,407 @@ PublishCoverageResults ###################### -.. todo:: PublishCoverageResults:Needs documentation. +The ``PublishCoverageResults`` job template downloads artifacts provided by :ref:`JOBTMPL/UnitTesting` containing code +coverage databases created by `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 `CodeCov `__ or +`Codacy `__. -**Behavior:** +.. topic:: Features -.. todo:: PublishCoverageResults:Behavior needs documentation. + * 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. -**Dependencies:** +.. topic:: Behavior -.. todo:: PublishCoverageResults:Dependencies needs documentation. + 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 ************* -Simple Example -============== +The following -.. todo:: PublishCoverageResults:Simple example needs documentation. \ No newline at end of file +.. code-block:: yaml + + name: Pipeline + + on: + push: + workflow_dispatch: + + jobs: + ConfigParams: + uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r5 + with: + package_name: myPackage + + UnitTestingParams: + uses: pyTooling/Actions/.github/workflows/Parameters.yml@r5 + with: + package_name: myPackage + + UnitTesting: + uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r5 + 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@r5 + needs: + - ConfigParams + - UnitTestingParams + - UnitTesting + with: + coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} + coverage_report_json_directory: ${{ needs.ConfigParams.outputs.coverage_report_json_directory }} + coverage_report_json_filename: ${{ needs.ConfigParams.outputs.coverage_report_json_filename }} + coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }} + coverage_report_html_directory: ${{ needs.ConfigParams.outputs.coverage_report_html_directory }} + codecov: 'true' + codacy: 'true' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + CODACY_TOKEN: ${{ secrets.CODACY_TOKEN }} + + +.. seealso:: + + :ref:`JOBTMPL/UnitTesting` + ``UnitTesting`` is usualy + + +.. _JOBTMPL/PublishCoverageResults/Parameters: + +Parameter Summary +***************** + +.. rubric:: Goto :ref:`input parameters ` + ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| 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_sqlite_artifact` | no | string | ``''`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_xml_artifact` | no | string | ``''`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_xml_directory` | no | string | ``'report/coverage'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_xml_filename` | no | string | ``'coverage.xml'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_json_artifact` | no | string | ``''`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_json_directory` | no | string | ``'report/coverage'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_json_filename` | no | string | ``'coverage.json'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_html_artifact` | no | string | ``''`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/coverage_report_html_directory` | no | string | ``'report/coverage/html'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/codecov` | no | string | ``'false'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ +| :ref:`JOBTMPL/PublishCoverageResults/Input/codacy` | no | string | ``'false'`` | ++-----------------------------------------------------------------------------+----------+----------+-------------------------------------------------------------------+ + + +.. rubric:: Goto :ref:`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 ` + +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_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_report_xml_directory: + +coverage_report_xml_directory +============================= + +:Type: string +:Required: no +:Default Value: ``'report/coverage'`` +:Possible Values: tbd +:Description: tbd + + +.. _JOBTMPL/PublishCoverageResults/Input/coverage_report_xml_filename: + +coverage_report_xml_filename +============================ + +:Type: string +:Required: no +:Default Value: ``'coverage.xml'`` +:Possible Values: tbd +:Description: tbd + + +.. _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_report_json_directory: + +coverage_report_json_directory +============================== + +:Type: string +:Required: no +:Default Value: ``'report/coverage'`` +:Possible Values: tbd +:Description: tbd + + +.. _JOBTMPL/PublishCoverageResults/Input/coverage_report_json_filename: + +coverage_report_json_filename +============================= + +:Type: string +:Required: no +:Default Value: ``'coverage.json'`` +:Possible Values: tbd +:Description: tbd + + +.. _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/coverage_report_html_directory: + +coverage_report_html_directory +============================== + +:Type: string +:Required: no +:Default Value: ``''`` +:Possible Values: tbd +:Description: tbd + + +.. _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 `CodeCov `__. + + +.. _JOBTMPL/PublishCoverageResults/Secret/CODACY_TOKEN: + +CODACY_TOKEN +============ + +:Type: string +:Required: no +:Default Value: — — — — +:Description: The token to publish code coverage results to `Codacy `__. + + + +.. _JOBTMPL/PublishCoverageResults/Outputs: + +Outputs +******* + +This job template has no output parameters. diff --git a/doc/_static/pyTooling-Actions-PublishCoverageResults.png b/doc/_static/pyTooling-Actions-PublishCoverageResults.png new file mode 100644 index 0000000..72c3314 Binary files /dev/null and b/doc/_static/pyTooling-Actions-PublishCoverageResults.png differ