Files
Actions/.github/workflows/CompletePipeline.yml
2026-01-08 17:55:53 +01:00

492 lines
22 KiB
YAML

# ==================================================================================================================== #
# 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@dev
ConfigParams:
uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@dev
UnitTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@dev
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@dev
# 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@dev
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@dev
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@dev
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@dev
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@dev
needs:
- UnitTestingParams
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
directory: ${{ needs.UnitTestingParams.outputs.package_directory }}
Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@dev
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@dev
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@dev
# 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@dev
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@dev
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@dev
# needs:
# - UnitTestingParams
# with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
Documentation:
uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@dev
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@dev
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@dev
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@dev
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@dev
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@dev
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@dev
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@dev
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 }}