# ==================================================================================================================== # # Authors: # # Patrick Lehmann # # # # ==================================================================================================================== # # Copyright 2020-2026 The pyTooling Authors # # # # Licensed under the Apache License, Version 2.0 (the "License"); # # you may not use this file except in compliance with the License. # # You may obtain a copy of the License at # # # # http://www.apache.org/licenses/LICENSE-2.0 # # # # Unless required by applicable law or agreed to in writing, software # # distributed under the License is distributed on an "AS IS" BASIS, # # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # # See the License for the specific language governing permissions and # # limitations under the License. # # # # SPDX-License-Identifier: Apache-2.0 # # ==================================================================================================================== # name: Namespace Package on: workflow_call: inputs: package_namespace: description: 'Name of the tool''s namespace.' required: false default: '' type: string package_name: description: 'Name of the tool''s package.' required: true type: string unittest_python_version: description: 'Python version.' required: false default: '3.14' type: string unittest_python_version_list: description: 'Space separated list of Python versions to run tests with.' required: false default: '3.10 3.11 3.12 3.13 3.14' type: string unittest_system_list: description: 'Space separated list of systems to run tests on.' required: false default: 'ubuntu ubuntu-arm windows windows-arm macos macos-arm mingw64 ucrt64' type: string unittest_include_list: description: 'Space separated list of system:python items to be included into the list of test.' required: false default: '' type: string unittest_exclude_list: description: 'Space separated list of system:python items to be excluded from the list of test.' required: false default: 'windows-arm:3.9 windows-arm:3.10' type: string unittest_disable_list: description: 'Space separated list of system:python items to be disabled from the list of test.' required: false default: 'windows-arm:pypy-3.10 windows-arm:pypy-3.11' type: string apptest_python_version: description: 'Python version.' required: false default: '3.14' type: string apptest_python_version_list: description: 'Space separated list of Python versions to run tests with.' required: false default: '' type: string apptest_system_list: description: 'Space separated list of systems to run tests on.' required: false default: 'ubuntu ubuntu-arm windows windows-arm macos macos-arm ucrt64' type: string apptest_include_list: description: 'Space separated list of system:python items to be included into the list of test.' required: false default: '' type: string apptest_exclude_list: description: 'Space separated list of system:python items to be excluded from the list of test.' required: false default: 'windows-arm:3.9 windows-arm:3.10' type: string apptest_disable_list: description: 'Space separated list of system:python items to be disabled from the list of test.' required: false default: 'windows-arm:pypy-3.10 windows-arm:pypy-3.11' type: string bandit: description: 'Run Static Application Security Testing (SAST) using Bandit.' required: false default: 'false' type: string pylint: description: 'Run Python linting using pylint.' required: false default: 'false' type: string codecov: description: 'Publish merged coverage and unittest reports to Codecov.' required: false default: 'false' type: string codacy: description: 'Publish merged coverage report to Codacy.' required: false default: 'false' type: string dorny: description: 'Publish merged unittest report via Dorny Test-Reporter.' required: false default: 'false' type: string cleanup: description: 'Cleanup artifacts afterwards.' required: false default: 'true' type: string secrets: PYPI_TOKEN: description: "Token for pushing releases to PyPI." required: false CODECOV_TOKEN: description: "Token for pushing coverage and unittest results to Codecov." required: false CODACY_TOKEN: description: "Token for pushing coverage results to Codacy." required: false jobs: Prepare: uses: pyTooling/Actions/.github/workflows/PrepareJob.yml@r7 ConfigParams: uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r7 UnitTestingParams: uses: pyTooling/Actions/.github/workflows/Parameters.yml@r7 with: package_namespace: ${{ inputs.package_namespace }} package_name: ${{ inputs.package_name }} python_version: ${{ inputs.unittest_python_version }} python_version_list: ${{ inputs.unittest_python_version_list }} system_list: ${{ inputs.unittest_system_list }} include_list: ${{ inputs.unittest_include_list }} exclude_list: ${{ inputs.unittest_exclude_list }} disable_list: ${{ inputs.unittest_disable_list }} # AppTestingParams: # uses: pyTooling/Actions/.github/workflows/Parameters.yml@r7 # with: # package_namespace: ${{ inputs.package_namespace }} # package_name: ${{ inputs.package_name }} # python_version: ${{ inputs.apptest_python_version }} # python_version_list: ${{ inputs.apptest_python_version_list }} # system_list: ${{ inputs.apptest_system_list }} # include_list: ${{ inputs.apptest_include_list }} # exclude_list: ${{ inputs.apptest_exclude_list }} # disable_list: ${{ inputs.apptest_disable_list }} InstallParams: uses: pyTooling/Actions/.github/workflows/Parameters.yml@r7 with: package_namespace: ${{ inputs.package_namespace }} package_name: ${{ inputs.package_name }} python_version: ${{ inputs.unittest_python_version }} python_version_list: '' system_list: ${{ inputs.unittest_system_list }} include_list: ${{ inputs.unittest_include_list }} exclude_list: ${{ inputs.unittest_exclude_list }} disable_list: ${{ inputs.unittest_disable_list }} VersionCheck: name: '' runs-on: 'ubuntu-24.04' needs: - Prepare - UnitTestingParams if: needs.Prepare.outputs.version != '' && needs.UnitTestingParams.outputs.package_version_file != '' outputs: code_version: ${{ steps.extract.outputs.code_version }} steps: - name: ⏬ Checkout repository uses: actions/checkout@v6 with: # The command 'git describe' (used for version) needs the history. fetch-depth: 0 - name: 🔧 Install pyTooling dependencies (native) run: | python -m pip install --disable-pip-version-check -U pyTooling - name: Extract version from Python source file id: extract if: endsWith(needs.UnitTestingParams.outputs.package_version_file, '.py') shell: python run: | from pathlib import Path from sys import exit from pyTooling.Packaging import extractVersionInformation expectedVersion = "${{ needs.Prepare.outputs.version }}".strip() versionFile = Path("${{ needs.UnitTestingParams.outputs.package_version_file }}") if not versionFile.exists(): print(f"::error title=CompletePipeline::Version file '{versionFile}' not found.") exit(1) versionInformation = extractVersionInformation(versionFile) print(f"expected: {expectedVersion}") print(f"from code: {versionInformation.Version}") if expectedVersion != versionInformation.Version: print(f"::error title=CompletePipeline::Expected version does not version in Python code.") exit(2) # Write jobs to special file github_output = Path(getenv("GITHUB_OUTPUT")) print(f"GITHUB_OUTPUT: {github_output}") with github_output.open("a+", encoding="utf-8") as f: f.write(dedent(f"""\ code_version={versionInformation.Version} """)) UnitTesting: uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r7 needs: - ConfigParams - UnitTestingParams with: jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }} # TODO: shouldn't this be configured by a parameter? Same as directories unittest_report_xml: ${{ needs.ConfigParams.outputs.unittest_report_xml }} coverage_report_xml: ${{ needs.ConfigParams.outputs.coverage_report_xml }} coverage_report_json: ${{ needs.ConfigParams.outputs.coverage_report_json }} coverage_report_html: ${{ needs.ConfigParams.outputs.coverage_report_html }} unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} StaticTypeCheck: uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r7 needs: - ConfigParams - UnitTestingParams with: python_version: ${{ needs.UnitTestingParams.outputs.python_version }} cobertura_report: ${{ needs.ConfigParams.outputs.typing_report_cobertura }} junit_report: ${{ needs.ConfigParams.outputs.typing_report_junit }} html_report: ${{ needs.ConfigParams.outputs.typing_report_html }} cobertura_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_cobertura }} junit_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_junit }} html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} CodeQuality: uses: pyTooling/Actions/.github/workflows/CheckCodeQuality.yml@r7 needs: - UnitTestingParams with: python_version: ${{ needs.UnitTestingParams.outputs.python_version }} package_directory: ${{ needs.UnitTestingParams.outputs.package_directory }} bandit: ${{ inputs.bandit }} pylint: ${{ inputs.pylint }} artifact: CodeQuality DocCoverage: uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@r7 needs: - UnitTestingParams with: python_version: ${{ needs.UnitTestingParams.outputs.python_version }} directory: ${{ needs.UnitTestingParams.outputs.package_directory }} Package: uses: pyTooling/Actions/.github/workflows/Package.yml@r7 needs: - UnitTestingParams with: python_version: ${{ needs.UnitTestingParams.outputs.python_version }} artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} Install: uses: pyTooling/Actions/.github/workflows/InstallPackage.yml@r7 needs: - UnitTestingParams - InstallParams - Package with: jobs: ${{ needs.InstallParams.outputs.python_jobs }} wheel: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} package_name: ${{ needs.UnitTestingParams.outputs.package_fullname }} # AppTesting: # uses: pyTooling/Actions/.github/workflows/ApplicationTesting.yml@r7 # needs: # - AppTestingParams # - UnitTestingParams # - Package # with: # jobs: ${{ needs.AppTestingParams.outputs.python_jobs }} # wheel: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} # apptest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).apptesting_xml }} PublishCoverageResults: uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r7 needs: - ConfigParams - UnitTestingParams - UnitTesting if: success() || failure() with: # coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} # coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }} # coverage_report_xml_directory: ${{ needs.ConfigParams.outputs.coverage_report_xml_directory }} # coverage_report_xml_filename: ${{ needs.ConfigParams.outputs.coverage_report_xml_filename }} 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: ${{ inputs.codecov }} codacy: ${{ inputs.codacy }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} CODACY_TOKEN: ${{ secrets.CODACY_TOKEN }} PublishTestResults: uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r7 needs: - ConfigParams - UnitTestingParams - UnitTesting if: success() || failure() with: testsuite-summary-name: ${{ needs.UnitTestingParams.outputs.package_fullname }} merged_junit_filename: ${{ fromJson(needs.ConfigParams.outputs.unittest_merged_report_xml).filename }} merged_junit_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} dorny: ${{ inputs.dorny }} codecov: ${{ inputs.codecov }} secrets: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} # VerifyDocs: # uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@r7 # needs: # - UnitTestingParams # with: # python_version: ${{ needs.UnitTestingParams.outputs.python_version }} Documentation: uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@r7 needs: - ConfigParams - UnitTestingParams - PublishTestResults - PublishCoverageResults # - VerifyDocs if: success() || failure() with: python_version: ${{ needs.UnitTestingParams.outputs.python_version }} coverage_report_json: ${{ needs.ConfigParams.outputs.coverage_report_json }} unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }} latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }} IntermediateCleanUp: uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@r7 needs: - UnitTestingParams - PublishCoverageResults - PublishTestResults if: ( success() || failure() ) && inputs.cleanup == 'true' with: sqlite_coverage_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}- xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}- PDFDocumentation: uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@r7 needs: - UnitTestingParams - Documentation with: document: ${{ needs.UnitTestingParams.outputs.package_fullname }} latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }} pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }} can-fail: 'true' PublishToGitHubPages: uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r7 needs: - UnitTestingParams - Documentation # - PDFDocumentation - PublishCoverageResults - StaticTypeCheck with: doc: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }} coverage: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }} typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} TriggerTaggedRelease: uses: pyTooling/Actions/.github/workflows/TagReleaseCommit.yml@r7 needs: - Prepare - UnitTesting # - AppTesting # - StaticTypeCheck - Package - Install - PublishToGitHubPages if: needs.Prepare.outputs.is_release_commit == 'true' && github.event_name != 'schedule' permissions: contents: write # required for create tag actions: write # required for trigger workflow with: version: ${{ needs.Prepare.outputs.version }} auto_tag: ${{ needs.Prepare.outputs.is_release_commit }} secrets: inherit ReleasePage: uses: pyTooling/Actions/.github/workflows/PublishReleaseNotes.yml@r7 needs: - Prepare - UnitTesting # - AppTesting # - StaticTypeCheck - Package - Install - PublishToGitHubPages if: needs.Prepare.outputs.is_release_tag == 'true' permissions: contents: write actions: write with: tag: ${{ needs.Prepare.outputs.version }} secrets: inherit PublishOnPyPI: uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r7 needs: - Prepare - UnitTestingParams - Package - ReleasePage if: needs.Prepare.outputs.is_release_tag == 'true' with: python_version: ${{ needs.UnitTestingParams.outputs.python_version }} requirements: '-r dist/requirements.txt' artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} secrets: PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} ArtifactCleanUp: uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r7 needs: - UnitTestingParams - UnitTesting - StaticTypeCheck - Documentation # - PDFDocumentation - PublishTestResults - PublishCoverageResults - PublishToGitHubPages # - PublishOnPyPI - Install - IntermediateCleanUp if: inputs.cleanup == 'true' with: package: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} remaining: | ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }} # ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).apptesting_xml }}-* # ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }}