This commit is contained in:
Patrick Lehmann
2025-01-14 17:39:43 +01:00
45 changed files with 672 additions and 433 deletions

View File

@@ -10,9 +10,7 @@ updates:
- Dependencies - Dependencies
assignees: assignees:
- Paebbels - Paebbels
- umarcor
reviewers: reviewers:
- Paebbels - Paebbels
- umarcor
schedule: schedule:
interval: "daily" # Checks on Monday trough Friday. interval: "daily" # Checks on Monday trough Friday.

View File

@@ -231,10 +231,10 @@ jobs:
cd "${{ inputs.root_directory || '.' }}" cd "${{ inputs.root_directory || '.' }}"
[ -n '${{ inputs.apptest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=report/unit/TestReportSummary.xml' || unset PYTEST_ARGS [ -n '${{ inputs.apptest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=report/unit/TestReportSummary.xml' || unset PYTEST_ARGS
if [ -n '${{ inputs.coverage_config }}' ]; then if [ -n '${{ inputs.coverage_config }}' ]; then
echo "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }}" printf "%s\n" "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }} coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }}
else else
echo "python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }}" printf "%s\n" "python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }}"
python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }} python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.apptest_directory }}
fi fi

View File

@@ -38,7 +38,7 @@ jobs:
steps: steps:
- name: '❗ Deprecation message' - name: '❗ Deprecation message'
run: echo "::warning title=Deprecated::'BuildTheDocs.yml' is not maintained anymore. Please switch to 'SphinxDocumentation.yml', 'LaTeXDocumentation.yml' and 'ExtractConfiguration.yml'." run: printf "%s\n" "::warning title=Deprecated::'BuildTheDocs.yml' is not maintained anymore. Please switch to 'SphinxDocumentation.yml', 'LaTeXDocumentation.yml' and 'ExtractConfiguration.yml'."
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4

View File

@@ -59,14 +59,14 @@ jobs:
- name: 🔧 Install wheel,tomli and pip dependencies (native) - name: 🔧 Install wheel,tomli and pip dependencies (native)
run: | run: |
python -m pip install --disable-pip-version-check -U docstr_coverage interrogate python -m pip install --disable-pip-version-check -U docstr_coverage interrogate[png]
- name: Run 'interrogate' Documentation Coverage Check - name: Run 'interrogate' Documentation Coverage Check
continue-on-error: true continue-on-error: true
run: | run: |
interrogate -c pyproject.toml --fail-under=${{ inputs.fail_under }} && echo "::error title=interrogate::Insufficient documentation quality (goal: ${{ inputs.fail_under }})" interrogate -c pyproject.toml --fail-under=${{ inputs.fail_under }} && printf "%s\n" "::error title=interrogate::Insufficient documentation quality (goal: ${{ inputs.fail_under }})"
- name: Run 'docstr_coverage' Documentation Coverage Check - name: Run 'docstr_coverage' Documentation Coverage Check
continue-on-error: true continue-on-error: true
run: | run: |
docstr-coverage -v 2 --fail-under=${{ inputs.fail_under }} ${{ inputs.directory }} && echo "::error title=docstr-coverage::Insufficient documentation quality (goal: ${{ inputs.fail_under }})" docstr-coverage -v 2 --fail-under=${{ inputs.fail_under }} ${{ inputs.directory }} && printf "%s\n" "::error title=docstr-coverage::Insufficient documentation quality (goal: ${{ inputs.fail_under }})"

View File

@@ -103,13 +103,13 @@ on:
jobs: jobs:
ConfigParams: ConfigParams:
uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r2 uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r4
with: with:
package_namespace: ${{ inputs.package_namespace }} package_namespace: ${{ inputs.package_namespace }}
package_name: ${{ inputs.package_name }} package_name: ${{ inputs.package_name }}
UnitTestingParams: UnitTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
package_namespace: ${{ inputs.package_namespace }} package_namespace: ${{ inputs.package_namespace }}
package_name: ${{ inputs.package_name }} package_name: ${{ inputs.package_name }}
@@ -121,7 +121,7 @@ jobs:
disable_list: ${{ inputs.unittest_disable_list }} disable_list: ${{ inputs.unittest_disable_list }}
AppTestingParams: AppTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
package_namespace: ${{ inputs.package_namespace }} package_namespace: ${{ inputs.package_namespace }}
package_name: ${{ inputs.package_name }} package_name: ${{ inputs.package_name }}
@@ -133,18 +133,22 @@ jobs:
disable_list: ${{ inputs.apptest_disable_list }} disable_list: ${{ inputs.apptest_disable_list }}
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r2 uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r4
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
with: with:
jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }} jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }}
requirements: "-r tests/unit/requirements.txt" requirements: "-r tests/unit/requirements.txt"
# pacboy: "msys/git python-lxml:p" # pacboy: "msys/git python-lxml:p"
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} unittest_report_xml_filename: ${{ needs.ConfigParams.outputs.unittest_report_xml_filename }}
coverage_report_html_directory: ${{ needs.ConfigParams.outputs.coverage_report_html_directory }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
StaticTypeCheck: StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r2 uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r4
needs: needs:
- ConfigParams - ConfigParams
- UnitTestingParams - UnitTestingParams
@@ -157,7 +161,7 @@ jobs:
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
DocCoverage: DocCoverage:
uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@r2 uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@r4
needs: needs:
- ConfigParams - ConfigParams
- UnitTestingParams - UnitTestingParams
@@ -167,7 +171,7 @@ jobs:
# fail_below: 70 # fail_below: 70
Package: Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@r2 uses: pyTooling/Actions/.github/workflows/Package.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- UnitTesting - UnitTesting
@@ -176,7 +180,7 @@ jobs:
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
# AppTesting: # AppTesting:
# uses: pyTooling/Actions/.github/workflows/ApplicationTesting.yml@r2 # uses: pyTooling/Actions/.github/workflows/ApplicationTesting.yml@r4
# needs: # needs:
# - AppTestingParams # - AppTestingParams
# - UnitTestingParams # - UnitTestingParams
@@ -187,7 +191,7 @@ jobs:
# apptest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).apptesting_xml }} # apptest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).apptesting_xml }}
PublishCoverageResults: PublishCoverageResults:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r2 uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- UnitTesting - UnitTesting
@@ -200,22 +204,23 @@ jobs:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }} codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishTestResults: PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r2 uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- UnitTesting - UnitTesting
with: with:
additional_merge_args: '-d "--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit"'
merged_junit_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} merged_junit_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
# VerifyDocs: # VerifyDocs:
# uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@r2 # uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@r4
# needs: # needs:
# - UnitTestingParams # - UnitTestingParams
# with: # with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }} # python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
Documentation: Documentation:
uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@r2 uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@r4
needs: needs:
- ConfigParams - ConfigParams
- UnitTestingParams - UnitTestingParams
@@ -231,7 +236,7 @@ jobs:
latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }} latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
IntermediateCleanUp: IntermediateCleanUp:
uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@r2 uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- PublishCoverageResults - PublishCoverageResults
@@ -242,7 +247,7 @@ jobs:
xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}- xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-
# PDFDocumentation: # PDFDocumentation:
# uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@r2 # uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@r4
# needs: # needs:
# - UnitTestingParams # - UnitTestingParams
# - Documentation # - Documentation
@@ -252,7 +257,7 @@ jobs:
# pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }} # pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }}
PublishToGitHubPages: PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r2 uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- Documentation - Documentation
@@ -265,7 +270,7 @@ jobs:
typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
ReleasePage: ReleasePage:
uses: pyTooling/Actions/.github/workflows/Release.yml@r2 uses: pyTooling/Actions/.github/workflows/Release.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- Package - Package
@@ -273,7 +278,7 @@ jobs:
- PublishToGitHubPages - PublishToGitHubPages
PublishOnPyPI: PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r2 uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- UnitTestingParams - UnitTestingParams
@@ -286,7 +291,7 @@ jobs:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r2 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- UnitTesting - UnitTesting

View File

@@ -72,7 +72,7 @@ jobs:
steps: steps:
- name: '❗ Deprecation message' - name: '❗ Deprecation message'
run: echo "::warning title=Deprecated::'CoverageCollection.yml' is not maintained anymore. Please switch to 'UnitTesting.yml', 'PublishCoverageResults.yml' and 'PublishTestResults.yml'." run: printf "%s\n" "::warning title=Deprecated::'CoverageCollection.yml' is not maintained anymore. Please switch to 'UnitTesting.yml', 'PublishCoverageResults.yml' and 'PublishTestResults.yml'."
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -150,7 +150,7 @@ jobs:
ABSDIR=$(pwd) ABSDIR=$(pwd)
cd "${{ inputs.tests_directory || '.' }}" cd "${{ inputs.tests_directory || '.' }}"
[ -n '${{ inputs.coverage_config }}' ] && PYCOV_ARGS="--cov-config=${ABSDIR}/${{ inputs.coverage_config }}" || unset PYCOV_ARGS [ -n '${{ inputs.coverage_config }}' ] && PYCOV_ARGS="--cov-config=${ABSDIR}/${{ inputs.coverage_config }}" || unset PYCOV_ARGS
echo "python -m pytest -rA --cov=${ABSDIR} ${PYCOV_ARGS} ${{ inputs.unittest_directory }} --color=yes" printf "%s\n" "python -m pytest -rA --cov=${ABSDIR} ${PYCOV_ARGS} ${{ inputs.unittest_directory }} --color=yes"
python -m pytest -rA --cov=${ABSDIR} $PYCOV_ARGS ${{ inputs.unittest_directory }} --color=yes python -m pytest -rA --cov=${ABSDIR} $PYCOV_ARGS ${{ inputs.unittest_directory }} --color=yes
- name: Convert to cobertura format - name: Convert to cobertura format

View File

@@ -59,18 +59,33 @@ on:
mypy_prepare_command: mypy_prepare_command:
description: "" description: ""
value: ${{ jobs.Extract.outputs.mypy_prepare_command }} value: ${{ jobs.Extract.outputs.mypy_prepare_command }}
unittest_report_xml_directory:
description: ""
value: ${{ jobs.Extract.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename:
description: ""
value: ${{ jobs.Extract.outputs.unittest_report_xml_filename }}
unittest_report_xml:
description: ""
value: ${{ jobs.Extract.outputs.unittest_report_xml }}
coverage_report_html_directory: coverage_report_html_directory:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_html_directory }} value: ${{ jobs.Extract.outputs.coverage_report_html_directory }}
coverage_report_xml_directory: coverage_report_xml_directory:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml_directory }} value: ${{ jobs.Extract.outputs.coverage_report_xml_directory }}
coverage_report_xml_filename:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml_filename }}
coverage_report_xml: coverage_report_xml:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml }} value: ${{ jobs.Extract.outputs.coverage_report_xml }}
coverage_report_json_directory: coverage_report_json_directory:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json_directory }} value: ${{ jobs.Extract.outputs.coverage_report_json_directory }}
coverage_report_json_filename:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json_filename }}
coverage_report_json: coverage_report_json:
description: "" description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json }} value: ${{ jobs.Extract.outputs.coverage_report_json }}
@@ -83,10 +98,15 @@ jobs:
package_fullname: ${{ steps.getPackageName.outputs.package_fullname }} package_fullname: ${{ steps.getPackageName.outputs.package_fullname }}
package_directory: ${{ steps.getPackageName.outputs.package_directory }} package_directory: ${{ steps.getPackageName.outputs.package_directory }}
mypy_prepare_command: ${{ steps.getPackageName.outputs.mypy_prepare_command }} mypy_prepare_command: ${{ steps.getPackageName.outputs.mypy_prepare_command }}
unittest_report_xml_directory: ${{ steps.getVariables.outputs.unittest_report_xml_directory }}
unittest_report_xml_filename: ${{ steps.getVariables.outputs.unittest_report_xml_filename }}
unittest_report_xml: ${{ steps.getVariables.outputs.unittest_report_xml }}
coverage_report_html_directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }} coverage_report_html_directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
coverage_report_xml_directory: ${{ steps.getVariables.outputs.coverage_report_xml_directory }} coverage_report_xml_directory: ${{ steps.getVariables.outputs.coverage_report_xml_directory }}
coverage_report_xml_filename: ${{ steps.getVariables.outputs.coverage_report_xml_filename }}
coverage_report_xml: ${{ steps.getVariables.outputs.coverage_report_xml }} coverage_report_xml: ${{ steps.getVariables.outputs.coverage_report_xml }}
coverage_report_json_directory: ${{ steps.getVariables.outputs.coverage_report_json_directory }} coverage_report_json_directory: ${{ steps.getVariables.outputs.coverage_report_json_directory }}
coverage_report_json_filename: ${{ steps.getVariables.outputs.coverage_report_json_filename }}
coverage_report_json: ${{ steps.getVariables.outputs.coverage_report_json }} coverage_report_json: ${{ steps.getVariables.outputs.coverage_report_json }}
steps: steps:
@@ -144,10 +164,11 @@ jobs:
from tomli import load as tomli_load from tomli import load as tomli_load
htmlDirectory = Path("htmlcov") unittestXMLFile = Path("./unittest.xml")
xmlFile = Path("./coverage.xml") coverageHTMLDirectory = Path("htmlcov")
jsonFile = Path("./coverage.json") coverageXMLFile = Path("./coverage.xml")
coverageRC = "${{ inputs.coverage_config }}".strip() coverageJSONFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file # Read output paths from 'pyproject.toml' file
if coverageRC == "pyproject.toml": if coverageRC == "pyproject.toml":
@@ -156,9 +177,10 @@ jobs:
with pyProjectFile.open("rb") as file: with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file) pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"]) unittestXMLFile = Path(pyProjectSettings["tool"]["pytest"]["junit_xml"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"]) coverageHTMLDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"]) coverageXMLFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
coverageJSONFile= Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else: else:
print(f"File '{pyProjectFile}' not found.") print(f"File '{pyProjectFile}' not found.")
print(f"::error title=FileNotFoundError::File '{pyProjectFile}' not found.") print(f"::error title=FileNotFoundError::File '{pyProjectFile}' not found.")
@@ -171,9 +193,9 @@ jobs:
with coverageRCFile.open("rb") as file: with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file) coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"]) coverageHTMLDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"]) coverageXMLFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"]) coverageJSONFile = Path(coverageRCSettings["json"]["output"])
else: else:
print(f"File '{coverageRCFile}' not found.") print(f"File '{coverageRCFile}' not found.")
print(f"::error title=FileNotFoundError::File '{coverageRCFile}' not found.") print(f"::error title=FileNotFoundError::File '{coverageRCFile}' not found.")
@@ -184,11 +206,16 @@ jobs:
print(f"GITHUB_OUTPUT: {github_output}") print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+", encoding="utf-8") as f: with github_output.open("a+", encoding="utf-8") as f:
f.write(dedent(f"""\ f.write(dedent(f"""\
coverage_report_html_directory={htmlDirectory.as_posix()} unittest_report_xml_directory={unittestXMLFile.parent.as_posix()}
coverage_report_xml_directory={xmlFile.parent.as_posix()} unittest_report_xml_filename={unittestXMLFile.name}
coverage_report_xml={xmlFile.as_posix()} unittest_report_xml={unittestXMLFile.as_posix()}
coverage_report_json_directory={jsonFile.parent.as_posix()} coverage_report_html_directory={coverageHTMLDirectory.as_posix()}
coverage_report_json={jsonFile.as_posix()} coverage_report_xml_directory={coverageXMLFile.parent.as_posix()}
coverage_report_xml_filename={coverageXMLFile.name}
coverage_report_xml={coverageXMLFile.as_posix()}
coverage_report_json_directory={coverageJSONFile.parent.as_posix()}
coverage_report_json_filename={coverageJSONFile.name}
coverage_report_json={coverageJSONFile.as_posix()}
""")) """))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}") print(f"DEBUG:\n unittest xml: {unittestXMLFile}\n coverage html: {coverageHTMLDirectory}\n coverage xml: {coverageXMLFile}\n coverage json: {coverageJSONFile}")

View File

@@ -55,17 +55,28 @@ jobs:
name: ${{ inputs.latex_artifact }} name: ${{ inputs.latex_artifact }}
path: latex path: latex
- name: Compile LaTeX document - name: Debug
uses: xu-cheng/latex-action@master run: |
tree -pash .
- name: Build LaTeX document using 'pytooling/miktex:sphinx'
uses: addnab/docker-run-action@v3
with: with:
working_directory: latex image: pytooling/miktex:sphinx
root_file: ${{ inputs.document }}.tex options: -v ${{ github.workspace }}/latex:/latex --workdir /latex
run: |
which pdflatex
pwd
ls -lAh
latexmk -xelatex ${{ inputs.document }}.tex
- name: 📤 Upload 'PDF Documentation' artifact - name: 📤 Upload 'PDF Documentation' artifact
uses: pyTooling/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
if: inputs.pdf_artifact != '' if: inputs.pdf_artifact != ''
with: with:
name: ${{ inputs.pdf_artifact }} name: ${{ inputs.pdf_artifact }}
working-directory: latex
path: ${{ inputs.document }}.pdf path: ${{ inputs.document }}.pdf
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -68,6 +68,18 @@ on:
description: 'Multi-line string containing artifact:file:title asset descriptions.' description: 'Multi-line string containing artifact:file:title asset descriptions.'
required: true required: true
type: string type: string
inventory-json:
type: string
required: false
default: ''
inventory-version:
type: string
required: false
default: ''
inventory-categories:
type: string
required: false
default: ''
tarball-name: tarball-name:
type: string type: string
required: false required: false
@@ -97,23 +109,23 @@ jobs:
run: | run: |
set +e set +e
ANSI_LIGHT_RED="\e[91m" ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN="\e[92m" ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_LIGHT_YELLOW="\e[93m" ANSI_LIGHT_YELLOW=$'\x1b[93m'
ANSI_NOCOLOR="\e[0m" ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }} export GH_TOKEN=${{ github.token }}
echo -n "Deleting release '${{ inputs.nightly_name }}' ... " printf "%s" "Deleting release '${{ inputs.nightly_name }}' ... "
message="$(gh release delete ${{ inputs.nightly_name }} --yes 2>&1)" message="$(gh release delete ${{ inputs.nightly_name }} --yes 2>&1)"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
elif [[ "${message}" == "release not found" ]]; then elif [[ "${message}" == "release not found" ]]; then
echo -e "${ANSI_LIGHT_YELLOW}[NOT FOUND]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_YELLOW}[NOT FOUND]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't delete release '${{ inputs.nightly_name }}' -> Error: '${message}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't delete release '${{ inputs.nightly_name }}' -> Error: '${message}'.${ANSI_NOCOLOR}"
echo "::error title=InternalError::Couldn't delete release '${{ inputs.nightly_name }}' -> Error: '${message}'." printf "%s\n" "::error title=InternalError::Couldn't delete release '${{ inputs.nightly_name }}' -> Error: '${message}'."
exit 1 exit 1
fi fi
@@ -122,19 +134,19 @@ jobs:
run: | run: |
set +e set +e
ANSI_LIGHT_RED="\e[91m" ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN="\e[92m" ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_NOCOLOR="\e[0m" ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }} export GH_TOKEN=${{ github.token }}
addDraft="--draft" addDraft="--draft"
if ${{ inputs.prerelease }}; then if [[ "${{ inputs.prerelease }}" == "true" ]]; then
addPreRelease="--prerelease" addPreRelease="--prerelease"
fi fi
if ! ${{ inputs.latest }}; then if [[ "${{ inputs.latest }}" == "false" ]]; then
addLatest="--latest=false" addLatest="--latest=false"
fi fi
@@ -166,14 +178,14 @@ jobs:
Published from [${{ github.workflow }}](https://github.com/Paebbels/ghdl/actions/runs/${{ github.run_id }}) workflow triggered by @${{ github.actor }} on $(date '+%Y-%m-%d %H:%M:%S'). Published from [${{ github.workflow }}](https://github.com/Paebbels/ghdl/actions/runs/${{ github.run_id }}) workflow triggered by @${{ github.actor }} on $(date '+%Y-%m-%d %H:%M:%S').
EOF EOF
echo "Creating release '${{ inputs.nightly_name }}' ... " printf "%s\n" "Creating release '${{ inputs.nightly_name }}' ... "
message="$(gh release create "${{ inputs.nightly_name }}" --verify-tag $addDraft $addPreRelease $addLatest "${addTitle[@]}" "${addNotes[@]}" 2>&1)" message="$(gh release create "${{ inputs.nightly_name }}" --verify-tag $addDraft $addPreRelease $addLatest "${addTitle[@]}" "${addNotes[@]}" 2>&1)"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't create release '${{ inputs.nightly_name }}' -> Error: '${message}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't create release '${{ inputs.nightly_name }}' -> Error: '${message}'.${ANSI_NOCOLOR}"
echo "::error title=InternalError::Couldn't create release '${{ inputs.nightly_name }}' -> Error: '${message}'." printf "%s\n" "::error title=InternalError::Couldn't create release '${{ inputs.nightly_name }}' -> Error: '${message}'."
exit 1 exit 1
fi fi
@@ -182,10 +194,11 @@ jobs:
run: | run: |
set +e set +e
ANSI_LIGHT_RED="\e[91m" ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN="\e[92m" ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_LIGHT_YELLOW="\e[93m" ANSI_LIGHT_YELLOW=$'\x1b[93m'
ANSI_NOCOLOR="\e[0m" ANSI_LIGHT_BLUE="\e[94m"
ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }} export GH_TOKEN=${{ github.token }}
@@ -199,9 +212,42 @@ jobs:
replacement="${patternLine#*=}" replacement="${patternLine#*=}"
line="${line//"%$pattern%"/"$replacement"}" line="${line//"%$pattern%"/"$replacement"}"
done <<<'${{ inputs.replacements }}' done <<<'${{ inputs.replacements }}'
echo "$line" printf "%s\n" "$line"
} }
# Create JSON inventory
if [[ "${{ inputs.inventory-json }}" != "" ]]; then
VERSION="1.0"
# Split categories by ',' into a Bash array.
# See https://stackoverflow.com/a/45201229/3719459
if [[ "${{ inputs.inventory-categories }}" != "" ]]; then
readarray -td, inventoryCategories <<<"${{ inputs.inventory-categories }},"
unset 'inventoryCategories[-1]'
declare -p inventoryCategories
else
inventoryCategories=""
fi
jsonInventory=$(jq -c -n \
--arg version "${VERSION}" \
--arg date "$(date +"%Y-%m-%dT%H-%M-%S%:z")" \
--argjson jsonMeta "$(jq -c -n \
--arg tag "${{ inputs.nightly_name }}" \
--arg version "${{ inputs.inventory-version }}" \
--arg hash "${{ github.sha }}" \
--arg repo "${{ github.server_url }}/${{ github.repository }}" \
--arg release "${{ github.server_url }}/${{ github.repository }}/releases/download/${{ inputs.nightly_name }}" \
--argjson categories "$(jq -c -n \
'$ARGS.positional' \
--args "${inventoryCategories[@]}" \
)" \
'{"tag": $tag, "version": $version, "git-hash": $hash, "repository-url": $repo, "release-url": $release, "categories": $categories}' \
)" \
'{"version": 1.0, "timestamp": $date, "meta": $jsonMeta, "files": {}}'
)
fi
ERRORS=0 ERRORS=0
# A dictionary of 0/1 to avoid duplicate downloads # A dictionary of 0/1 to avoid duplicate downloads
declare -A downloadedArtifacts declare -A downloadedArtifacts
@@ -214,184 +260,243 @@ jobs:
# split assetLine colon separated triple: artifact:asset:title # split assetLine colon separated triple: artifact:asset:title
artifact="${assetLine%%:*}" artifact="${assetLine%%:*}"
remaining="${assetLine#*:}" assetLine="${assetLine#*:}"
asset="${remaining%%:*}" asset="${assetLine%%:*}"
title="${remaining##*:}" assetLine="${assetLine#*:}"
if [[ "${{ inputs.inventory-json }}" == "" ]]; then
categories=""
title="${assetLine##*:}"
else
categories="${assetLine%%:*}"
title="${assetLine##*:}"
fi
# remove leading whitespace # remove leading whitespace
asset="${asset#"${asset%%[![:space:]]*}"}" asset="${asset#"${asset%%[![:space:]]*}"}"
categories="${categories#"${categories%%[![:space:]]*}"}"
title="${title#"${title%%[![:space:]]*}"}" title="${title#"${title%%[![:space:]]*}"}"
# apply replacements # apply replacements
asset="$(Replace "${asset}")" asset="$(Replace "${asset}")"
title="$(Replace "${title}")" title="$(Replace "${title}")"
echo "Publish asset '${asset}' from artifact '${artifact}' with title '${title}'" printf "%s\n" "Publish asset '${asset}' from artifact '${artifact}' with title '${title}'"
echo -n " Checked asset for duplicates ... " printf " %s" "Checked asset for duplicates ... "
if [[ -n "${assetFilenames[$asset]}" ]]; then if [[ -n "${assetFilenames[$asset]}" ]]; then
echo -e "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo "::error title=DuplicateAsset::Asset '${asset}' from artifact '${artifact}' was already uploaded to release '${{ inputs.nightly_name }}'." printf "%s\n" "::error title=DuplicateAsset::Asset '${asset}' from artifact '${artifact}' was already uploaded to release '${{ inputs.nightly_name }}'."
ERRORS=1 ERRORS=1
continue continue
else else
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
assetFilenames[$asset]=1 assetFilenames[$asset]=1
fi fi
# Download artifact by artifact name # Download artifact by artifact name
if [[ -n "${downloadedArtifacts[$artifact]}" ]]; then if [[ -n "${downloadedArtifacts[$artifact]}" ]]; then
echo -e " downloading '${artifact}' ... ${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}" printf " %s\n" "downloading '${artifact}' ... ${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}"
else else
echo " downloading '${artifact}' ... " echo " downloading '${artifact}' ... "
echo -n " gh run download $GITHUB_RUN_ID --dir \"${artifact}\" --name \"${artifact}\" " printf " %s" "gh run download $GITHUB_RUN_ID --dir \"${artifact}\" --name \"${artifact}\" "
gh run download $GITHUB_RUN_ID --dir "${artifact}" --name "${artifact}" gh run download $GITHUB_RUN_ID --dir "${artifact}" --name "${artifact}"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't download artifact '${artifact}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't download artifact '${artifact}'.${ANSI_NOCOLOR}"
echo "::error title=ArtifactNotFound::Couldn't download artifact '${artifact}'." printf "%s\n" "::error title=ArtifactNotFound::Couldn't download artifact '${artifact}'."
ERRORS=1 ERRORS=1
continue continue
fi fi
downloadedArtifacts[$artifact]=1 downloadedArtifacts[$artifact]=1
echo -n " Checking for embedded tarball ... " printf " %s" "Checking for embedded tarball ... "
if [[ -f "${artifact}/${{ inputs.tarball-name }}" ]]; then if [[ -f "${artifact}/${{ inputs.tarball-name }}" ]]; then
echo -e "${ANSI_LIGHT_GREEN}[FOUND]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[FOUND]${ANSI_NOCOLOR}"
pushd "${artifact}" > /dev/null pushd "${artifact}" > /dev/null
echo -n " Extracting embedded tarball ... " printf " %s" "Extracting embedded tarball ... "
tar -xf "${{ inputs.tarball-name }}" tar -xf "${{ inputs.tarball-name }}"
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
fi fi
echo -n " Removing temporary tarball ... " printf " %s" "Removing temporary tarball ... "
rm -f "${{ inputs.tarball-name }}" rm -f "${{ inputs.tarball-name }}"
if [[ $? -ne 0 ]]; then if [[ $? -ne 0 ]]; then
echo -e "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
fi fi
popd > /dev/null popd > /dev/null
else else
echo -e "${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}"
fi fi
fi fi
# Check if artifact should be compressed (zip, tgz) or if asset was part of the downloaded artifact. # Check if artifact should be compressed (zip, tgz) or if asset was part of the downloaded artifact.
echo -n " checking asset '${artifact}/${asset}' ... " printf " %s" "checking asset '${artifact}/${asset}' ... "
if [[ "${asset}" == !*.zip ]]; then if [[ "${asset}" == !*.zip ]]; then
echo -e "${ANSI_LIGHT_GREEN}[ZIP]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[ZIP]${ANSI_NOCOLOR}"
asset="${asset##*!}" asset="${asset##*!}"
echo " Compressing artifact '${artifact}' to '${asset}' ..." printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
( (
cd "${artifact}" && \ cd "${artifact}" && \
zip -r "../${asset}" * zip -r "../${asset}" *
) )
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e " Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf " %s\n" "Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${asset}" uploadFile="${asset}"
else else
echo -e " Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf " %s\n" "Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to zip file '${asset}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to zip file '${asset}'.${ANSI_NOCOLOR}"
echo "::error title=CompressionError::Couldn't compress '${artifact}' to zip file '${asset}'." printf "%s\n" "::error title=CompressionError::Couldn't compress '${artifact}' to zip file '${asset}'."
ERRORS=1 ERRORS=1
continue continue
fi fi
elif [[ "${asset}" == !*.tgz || "${asset}" == !*.tar.gz || "${asset}" == \$*.tgz || "${asset}" == \$*.tar.gz ]]; then elif [[ "${asset}" == !*.tgz || "${asset}" == !*.tar.gz || "${asset}" == \$*.tgz || "${asset}" == \$*.tar.gz ]]; then
echo -e "${ANSI_LIGHT_GREEN}[TAR/GZ]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[TAR/GZ]${ANSI_NOCOLOR}"
if [[ "${asset:0:1}" == "\$" ]]; then if [[ "${asset:0:1}" == "\$" ]]; then
asset="${asset##*$}" asset="${asset##*$}"
dirName="${asset%.*}" dirName="${asset%.*}"
echo " Compressing artifact '${artifact}' to '${asset}' ..." printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
tar -c --gzip --file="${asset}" --directory="${artifact}" --transform "s|^\.|${dirName%.tar}|" . tar -c --gzip --owner=0 --group=0 --file="${asset}" --directory="${artifact}" --transform "s|^\.|${dirName%.tar}|" .
retCode=$? retCode=$?
else else
asset="${asset##*!}" asset="${asset##*!}"
echo " Compressing artifact '${artifact}' to '${asset}' ..." printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
( (
cd "${artifact}" && \ cd "${artifact}" && \
tar -c --gzip --file="../${asset}" * tar -c --gzip --owner=0 --group=0 --file="../${asset}" *
) )
retCode=$? retCode=$?
fi fi
if [[ $retCode -eq 0 ]]; then if [[ $retCode -eq 0 ]]; then
echo -e " Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf " %s\n" "Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${asset}" uploadFile="${asset}"
else else
echo -e " Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf " %s\n" "Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to tgz file '${asset}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to tgz file '${asset}'.${ANSI_NOCOLOR}"
echo "::error title=CompressionError::Couldn't compress '${artifact}' to tgz file '${asset}'." printf "%s\n" "::error title=CompressionError::Couldn't compress '${artifact}' to tgz file '${asset}'."
ERRORS=1 ERRORS=1
continue continue
fi fi
elif [[ "${asset}" == !*.tzst || "${asset}" == !*.tar.zst || "${asset}" == \$*.tzst || "${asset}" == \$*.tar.zst ]]; then elif [[ "${asset}" == !*.tzst || "${asset}" == !*.tar.zst || "${asset}" == \$*.tzst || "${asset}" == \$*.tar.zst ]]; then
echo -e "${ANSI_LIGHT_GREEN}[ZST]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[ZST]${ANSI_NOCOLOR}"
if [[ "${asset:0:1}" == "\$" ]]; then if [[ "${asset:0:1}" == "\$" ]]; then
asset="${asset##*$}" asset="${asset##*$}"
dirName="${asset%.*}" dirName="${asset%.*}"
echo " Compressing artifact '${artifact}' to '${asset}' ..." printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
tar -c --zstd --file="${asset}" --directory="${artifact}" --transform "s|^\.|${dirName%.tar}|" . tar -c --zstd --owner=0 --group=0 --file="${asset}" --directory="${artifact}" --transform "s|^\.|${dirName%.tar}|" .
retCode=$? retCode=$?
else else
asset="${asset##*!}" asset="${asset##*!}"
echo " Compressing artifact '${artifact}' to '${asset}' ..." printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
( (
cd "${artifact}" && \ cd "${artifact}" && \
tar -c --zstd --file="../${asset}" * tar -c --zstd --owner=0 --group=0 --file="../${asset}" *
) )
retCode=$? retCode=$?
fi fi
if [[ $retCode -eq 0 ]]; then if [[ $retCode -eq 0 ]]; then
echo -e " Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf " %s\n" "Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${asset}" uploadFile="${asset}"
else else
echo -e " Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf " %s\n" "Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to zst file '${asset}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to zst file '${asset}'.${ANSI_NOCOLOR}"
echo "::error title=CompressionError::Couldn't compress '${artifact}' to zst file '${asset}'." printf "%s\n" "::error title=CompressionError::Couldn't compress '${artifact}' to zst file '${asset}'."
ERRORS=1 ERRORS=1
continue continue
fi fi
elif [[ -e "${artifact}/${asset}" ]]; then elif [[ -e "${artifact}/${asset}" ]]; then
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${artifact}/${asset}" uploadFile="${artifact}/${asset}"
else else
echo -e "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't find asset '${asset}' in artifact '${artifact}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't find asset '${asset}' in artifact '${artifact}'.${ANSI_NOCOLOR}"
echo "::error title=FileNotFound::Couldn't find asset '${asset}' in artifact '${artifact}'." printf "%s\n" "::error title=FileNotFound::Couldn't find asset '${asset}' in artifact '${artifact}'."
ERRORS=1 ERRORS=1
continue continue
fi fi
# Add asset to JSON inventory
if [[ "${{ inputs.inventory-json }}" != "" ]]; then
if [[ "${categories}" != "${title}" ]]; then
printf " %s\n" "adding file '${uploadFile}' with '${categories//;/ → }' to JSON inventory ..."
category=""
jsonEntry=$(jq -c -n \
--arg title "${title}" \
--arg file "${uploadFile}" \
'{"file": $file, "title": $title}' \
)
while [[ "${categories}" != "${category}" ]]; do
category="${categories##*;}"
categories="${categories%;*}"
jsonEntry=$(jq -c -n --arg cat "${category}" --argjson value "${jsonEntry}" '{$cat: $value}')
done
jsonInventory=$(jq -c -n \
--argjson inventory "${jsonInventory}" \
--argjson file "${jsonEntry}" \
'$inventory * {"files": $file}' \
)
else
printf " %s\n" "adding file '${uploadFile}' to JSON inventory ... ${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}"
fi
fi
# Upload asset to existing release page # Upload asset to existing release page
echo -n " uploading asset '${asset}' from '${uploadFile}' with title '${title}' ... " printf " %s" "uploading asset '${asset}' from '${uploadFile}' with title '${title}' ... "
gh release upload ${{ inputs.nightly_name }} "${uploadFile}#${title}" --clobber gh release upload ${{ inputs.nightly_name }} "${uploadFile}#${title}" --clobber
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't upload asset '${asset}' from '${uploadFile}' to release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't upload asset '${asset}' from '${uploadFile}' to release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}"
echo "::error title=UploadError::Couldn't upload asset '${asset}' from '${uploadFile}' to release '${{ inputs.nightly_name }}'." printf "%s\n" "::error title=UploadError::Couldn't upload asset '${asset}' from '${uploadFile}' to release '${{ inputs.nightly_name }}'."
ERRORS=1 ERRORS=1
continue continue
fi fi
done <<<'${{ inputs.assets }}' done <<<'${{ inputs.assets }}'
echo "Inspecting downloaded artifacts ..." if [[ "${{ inputs.inventory-json }}" != "" ]]; then
tree -L 3 . inventoryTitle="Release Inventory (JSON)"
printf "%s\n" "Publish asset '${{ inputs.inventory-json }}' with title '${inventoryTitle}'"
printf "::group::${ANSI_LIGHT_BLUE}%s${ANSI_NOCOLOR}\n" "Writing JSON inventory to '${{ inputs.inventory-json }}' ...."
printf "%s\n" "$(jq -n --argjson inventory "${jsonInventory}" '$inventory')" > "${{ inputs.inventory-json }}"
cat "${{ inputs.inventory-json }}"
printf "::endgroup::\n"
# Upload inventory asset to existing release page
printf " %s" "uploading asset '${{ inputs.inventory-json }}' title '${inventoryTitle}' ... "
gh release upload ${{ inputs.nightly_name }} "${{ inputs.inventory-json }}#${inventoryTitle}" --clobber
if [[ $? -eq 0 ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
else
printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
printf "%s\n" "${ANSI_LIGHT_RED}Couldn't upload asset '${{ inputs.inventory-json }}' to release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=UploadError::Couldn't upload asset '${{ inputs.inventory-json }}' to release '${{ inputs.nightly_name }}'."
ERRORS=1
continue
fi
fi
printf "::group::${ANSI_LIGHT_BLUE}%s${ANSI_NOCOLOR}\n" "Inspecting downloaded artifacts ..."
tree -pash -L 3 .
printf "::endgroup::\n"
if [[ $ERROR -ne 0 ]]; then if [[ $ERROR -ne 0 ]]; then
echo -e "${ANSI_LIGHT_RED}Errors detected in previous steps.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Errors detected in previous steps.${ANSI_NOCOLOR}"
exit 1 exit 1
fi fi
@@ -400,19 +505,19 @@ jobs:
run: | run: |
set +e set +e
ANSI_LIGHT_RED="\e[91m" ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN="\e[92m" ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_NOCOLOR="\e[0m" ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }} export GH_TOKEN=${{ github.token }}
# Remove draft-state from release page # Remove draft-state from release page
echo -n "Remove draft-state from release '${title}' ... " printf "%s" "Remove draft-state from release '${title}' ... "
gh release edit --draft=false "${{ inputs.nightly_name }}" gh release edit --draft=false "${{ inputs.nightly_name }}"
if [[ $? -eq 0 ]]; then if [[ $? -eq 0 ]]; then
echo -e "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
else else
echo -e "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
echo -e "${ANSI_LIGHT_RED}Couldn't remove draft-state from release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}" printf "%s\n" "${ANSI_LIGHT_RED}Couldn't remove draft-state from release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}"
echo "::error title=ReleasePage::Couldn't remove draft-state from release '${{ inputs.nightly_name }}'." printf "%s\n" "::error title=ReleasePage::Couldn't remove draft-state from release '${{ inputs.nightly_name }}'."
fi fi

View File

@@ -147,7 +147,7 @@ jobs:
else: else:
name = f"{package_namespace}.{package_name}" name = f"{package_namespace}.{package_name}"
currentMSYS2Version = "3.11" currentMSYS2Version = "3.12"
currentAlphaVersion = "3.14" currentAlphaVersion = "3.14"
currentAlphaRelease = "3.14.0-alpha.1" currentAlphaRelease = "3.14.0-alpha.1"
@@ -337,7 +337,7 @@ jobs:
- name: Verify out parameters - name: Verify out parameters
id: verify id: verify
run: | run: |
echo 'python_version: ${{ steps.params.outputs.python_version }}' printf "python_version: %s\n" '${{ steps.params.outputs.python_version }}'
echo 'python_jobs: ${{ steps.params.outputs.python_jobs }}' printf "python_jobs: %s\n" '${{ steps.params.outputs.python_jobs }}'
echo 'artifact_names: ${{ steps.params.outputs.artifact_names }}' printf "artifact_names: %s\n" '${{ steps.params.outputs.artifact_names }}'
echo 'params: ${{ steps.params.outputs.params }}' printf "params: %s\n" '${{ steps.params.outputs.params }}'

View File

@@ -31,7 +31,7 @@ on:
type: string type: string
coverage_artifacts_pattern: coverage_artifacts_pattern:
required: false required: false
default: '*-CodeCoverage-*' default: '*-CodeCoverage-SQLite-*'
type: string type: string
coverage_config: coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.' description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
@@ -84,7 +84,7 @@ jobs:
- name: 🔎 Inspect extracted artifact (tarball) - name: 🔎 Inspect extracted artifact (tarball)
run: | run: |
tree -psh artifacts tree -pash artifacts
- name: 🔧 Install coverage and tomli - name: 🔧 Install coverage and tomli
run: | run: |
@@ -150,13 +150,11 @@ jobs:
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}") print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
- name: Rename .coverage files and collect them all to coverage/ - name: Rename .coverage files and move them all into 'coverage/'
run: | run: |
ls -lAh artifacts/
ls -lAh artifacts/*/.coverage
mkdir -p coverage mkdir -p coverage
find artifacts/ -type f -path "*SQLite*.coverage" -exec sh -c 'cp -v $0 "coverage/$(basename $0).$(basename $(dirname $0))"' {} ';' find artifacts/ -type f -path "*SQLite*.coverage" -exec sh -c 'cp -v $0 "coverage/$(basename $0).$(basename $(dirname $0))"' {} ';'
tree -a coverage tree -pash coverage
- name: Combine SQLite files (using Coverage.py) - name: Combine SQLite files (using Coverage.py)
run: coverage combine --data-file=.coverage coverage/ run: coverage combine --data-file=.coverage coverage/
@@ -177,7 +175,7 @@ jobs:
run: | run: |
coverage html --data-file=.coverage -d report/coverage/html coverage html --data-file=.coverage -d report/coverage/html
rm report/coverage/html/.gitignore rm report/coverage/html/.gitignore
tree -a report/coverage/html tree -pash report/coverage/html
- name: 📤 Upload 'Coverage SQLite Database' artifact - name: 📤 Upload 'Coverage SQLite Database' artifact
if: inputs.coverage_sqlite_artifact != '' if: inputs.coverage_sqlite_artifact != ''

View File

@@ -32,7 +32,7 @@ on:
type: string type: string
unittest_artifacts_pattern: unittest_artifacts_pattern:
required: false required: false
default: '*-UnitTestReportSummary-*' default: '*-UnitTestReportSummary-XML-*'
type: string type: string
merged_junit_artifact: merged_junit_artifact:
description: 'Name of the merged JUnit Test Summary artifact.' description: 'Name of the merged JUnit Test Summary artifact.'
@@ -73,23 +73,22 @@ jobs:
- name: 🔎 Inspect extracted artifact (tarball) - name: 🔎 Inspect extracted artifact (tarball)
run: | run: |
tree -psh artifacts tree -pash artifacts
- name: 🔧 Install pyEDAA.Reports (JUunit Parser and Merger) - name: 🔧 Install pyEDAA.Reports (JUunit Parser and Merger)
run: | run: |
python -m pip install --disable-pip-version-check --break-system-packages -U pyEDAA.Reports python -m pip install --disable-pip-version-check --break-system-packages -U pyEDAA.Reports
- name: Move JUnit files and collect them all to junit/ - name: Rename JUnit files and move them all into 'junit/'
run: | run: |
mkdir -p junit mkdir -p junit
ls -lAh artifacts/*/*.xml
find artifacts/ -type f -path "*TestReportSummary*.xml" -exec sh -c 'cp -v $0 "junit/$(basename $(dirname $0)).$(basename $0)"' {} ';' find artifacts/ -type f -path "*TestReportSummary*.xml" -exec sh -c 'cp -v $0 "junit/$(basename $(dirname $0)).$(basename $0)"' {} ';'
tree -a junit tree -pash junit
- name: 🔁 Merge JUnit Unit Test Summaries - name: 🔁 Merge JUnit Unit Test Summaries
run: | run: |
pyedaa-reports -v unittest "--merge=pyTest-JUnit:junit/*.xml" ${{ inputs.additional_merge_args }} "--output=pyTest-JUnit:Unittesting.xml" pyedaa-reports -v unittest "--merge=pyTest-JUnit:junit/*.xml" ${{ inputs.additional_merge_args }} "--output=pyTest-JUnit:Unittesting.xml"
echo "cat Unittesting.xml" printf "%s\n" "cat Unittesting.xml"
cat Unittesting.xml cat Unittesting.xml
- name: 📊 Publish Unit Test Results - name: 📊 Publish Unit Test Results

View File

@@ -55,7 +55,7 @@ jobs:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: 📥 Download artifacts '${{ inputs.doc }}' from 'BuildTheDocs' job - name: 📥 Download artifacts '${{ inputs.doc }}' from 'SphinxDocumentation' job
uses: pyTooling/download-artifact@v4 uses: pyTooling/download-artifact@v4
with: with:
name: ${{ inputs.doc }} name: ${{ inputs.doc }}

View File

@@ -180,6 +180,88 @@ jobs:
sphinx-build -v -n -b latex -d _build/doctrees -j $(nproc) -w _build/latex.log . _build/latex sphinx-build -v -n -b latex -d _build/doctrees -j $(nproc) -w _build/latex.log . _build/latex
# --builder html --doctree-dir _build/doctrees --verbose --fresh-env --write-all --nitpicky --warning-file _build/html.log . _build/html # --builder html --doctree-dir _build/doctrees --verbose --fresh-env --write-all --nitpicky --warning-file _build/html.log . _build/html
- name: Workaround I - https://github.com/sphinx-doc/sphinx/issues/13190
if: inputs.latex_artifact != ''
run: |
printf "Changing directory to 'doc/_build/latex' ...\n"
cd doc/_build/latex
MIMETYPE_EXTENSIONS=(
"image/png:png"
"image/jpeg:jpg"
"image/svg+xml:svg"
)
printf "Changing file extension according to MIME type ...\n"
while IFS=$'\n' read -r file; do
printf " Checking '%s' ... " "${file}"
mime="$(file --mime-type -b "${file}")"
printf "[%s]\n" "${mime}"
found=0
for MIME in "${MIMETYPE_EXTENSIONS[@]}"; do
mimetype="${MIME%%:*}"
extension="${MIME#*:}"
if [[ "${mime}" == "${mimetype}" && "${file##*.}" != "${extension}" ]]; then
printf " Rename file to '%s' " "${file}.${extension}"
mv "${file}" "${file}.${extension}"
if [[ $? -eq 0 ]]; then
printf "[OK]\n"
else
printf "[FAILED]\n"
fi
printf " Patching LaTeX file for '%s' " "${file}"
sed -i "s:{{${file%.*}}\.${file##*.}}:{{${file}}.${extension}}:g" *.tex
if [[ $? -eq 0 ]]; then
printf "[OK]\n"
else
printf "[FAILED]\n"
fi
found=1
break
fi
done
if [[ $found -eq 0 ]]; then
printf "[SKIPPED]\n"
fi
done <<<$(find . -type f -not -iname "*.cls" -not -iname "*.sty" -not -iname "*.xdy" -not -iname "*.svg" -not -iname "*.png" -not -iname "*.jpg" | sed 's:./::')
- name: Workaround II - https://github.com/sphinx-doc/sphinx/issues/13189
if: inputs.latex_artifact != ''
run: |
printf "Changing directory to 'doc/_build/latex' ...\n"
cd doc/_build/latex
printf "Searching for downloaded images, that need normalization ...\n"
for imageExt in png svg jpg jpeg; do
printf " Processing '%s' ...\n" "${imageExt}"
while IFS=$'\n' read -r imageFile; do
newFile="${imageFile//%/_}";
printf " %s\n" "$imageFile";
if [[ "${imageFile}" != "${newFile}" ]]; then
printf " Rename file to '%s' " "${newFile}"
mv "${imageFile}" "${newFile}"
if [[ $? -eq 0 ]]; then
printf "[OK]\n"
else
printf "[FAILED]\n"
fi
printf " Patching LaTeX file for '%s' " "${newFile}"
sed -i "s:{{${imageFile%.*}}\.${imageFile##*.}}:{{${newFile%.*}}.${newFile##*.}}:g" *.tex
if [[ $? -eq 0 ]]; then
printf "[OK]\n"
else
printf "[FAILED]\n"
fi
fi
done <<<$(find . -type f -iname "*.$imageExt" | sed 's:./::')
done
- name: 📤 Upload 'LaTeX Documentation' artifact - name: 📤 Upload 'LaTeX Documentation' artifact
if: inputs.latex_artifact != '' if: inputs.latex_artifact != ''
continue-on-error: true continue-on-error: true

View File

@@ -64,7 +64,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: echo "Build some tool and generate some (versioned) artifacts" > artifact-$(date -u +"%Y-%m-%dT%H-%M-%SZ").txt - run: printf "%s\n" "Build some tool and generate some (versioned) artifacts" > artifact-$(date -u +"%Y-%m-%dT%H-%M-%SZ").txt
- name: Single - name: Single
uses: ./releaser/composite uses: ./releaser/composite
@@ -84,7 +84,7 @@ jobs:
- name: Add artifacts/*.txt - name: Add artifacts/*.txt
run: | run: |
mkdir artifacts mkdir artifacts
echo "Build some tool and generate some artifacts" > artifacts/artifact.txt printf "%s\n" "Build some tool and generate some artifacts" > artifacts/artifact.txt
touch artifacts/empty_file.txt touch artifacts/empty_file.txt
- name: Single in subdir - name: Single in subdir
@@ -95,8 +95,8 @@ jobs:
- name: Add artifacts/*.md - name: Add artifacts/*.md
run: | run: |
echo "releaser hello" > artifacts/hello.md printf "%s\n" "releaser hello" > artifacts/hello.md
echo "releaser world" > artifacts/world.md printf "%s\n" "releaser world" > artifacts/world.md
- name: Directory wildcard - name: Directory wildcard
uses: ./releaser/composite uses: ./releaser/composite
@@ -107,7 +107,7 @@ jobs:
- name: Add artifacts/subdir - name: Add artifacts/subdir
run: | run: |
mkdir artifacts/subdir mkdir artifacts/subdir
echo "Test recursive glob" > artifacts/subdir/deep_file.txt printf "%s\n" "Test recursive glob" > artifacts/subdir/deep_file.txt
- name: Directory wildcard (recursive) - name: Directory wildcard (recursive)
uses: ./releaser/composite uses: ./releaser/composite
@@ -124,7 +124,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- run: echo "Build some tool and generate some (versioned) artifacts" > artifact-$(date -u +"%Y-%m-%dT%H-%M-%SZ").txt - run: printf "%s\n" "Build some tool and generate some (versioned) artifacts" > artifact-$(date -u +"%Y-%m-%dT%H-%M-%SZ").txt
- name: Single - name: Single
uses: ./releaser uses: ./releaser
@@ -144,7 +144,7 @@ jobs:
- name: Add artifacts/*.txt - name: Add artifacts/*.txt
run: | run: |
mkdir artifacts mkdir artifacts
echo "Build some tool and generate some artifacts" > artifacts/artifact.txt printf "%s\n" "Build some tool and generate some artifacts" > artifacts/artifact.txt
touch artifacts/empty_file.txt touch artifacts/empty_file.txt
- name: Single in subdir - name: Single in subdir
@@ -155,8 +155,8 @@ jobs:
- name: Add artifacts/*.md - name: Add artifacts/*.md
run: | run: |
echo "releaser hello" > artifacts/hello.md printf "%s\n" "releaser hello" > artifacts/hello.md
echo "releaser world" > artifacts/world.md printf "%s\n" "releaser world" > artifacts/world.md
- name: Directory wildcard - name: Directory wildcard
uses: ./releaser uses: ./releaser
@@ -167,7 +167,7 @@ jobs:
- name: Add artifacts/subdir - name: Add artifacts/subdir
run: | run: |
mkdir artifacts/subdir mkdir artifacts/subdir
echo "Test recursive glob" > artifacts/subdir/deep_file.txt printf "%s\n" "Test recursive glob" > artifacts/subdir/deep_file.txt
- name: Directory wildcard (recursive) - name: Directory wildcard (recursive)
uses: ./releaser uses: ./releaser

View File

@@ -94,11 +94,26 @@ on:
required: false required: false
default: 'unit' default: 'unit'
type: string type: string
unittest_report_xml_directory:
description: 'Path where to save the unittest summary report XML.'
required: false
default: 'report/unit'
type: string
unittest_report_xml_filename:
description: 'Filename of the unittest summary report XML.'
required: false
default: 'TestReportSummary.xml'
type: string
coverage_config: coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.' description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false required: false
default: 'pyproject.toml' default: 'pyproject.toml'
type: string type: string
coverage_report_html_directory:
description: ''
required: false
default: 'report/coverage/html'
type: string
unittest_xml_artifact: unittest_xml_artifact:
description: "Generate unit test report with junitxml and upload results as an artifact." description: "Generate unit test report with junitxml and upload results as an artifact."
required: false required: false
@@ -323,69 +338,6 @@ jobs:
if: matrix.system == 'msys2' && matrix.runtime == 'UCRT64' && inputs.ucrt64_before_script != '' if: matrix.system == 'msys2' && matrix.runtime == 'UCRT64' && inputs.ucrt64_before_script != ''
run: ${{ inputs.ucrt64_before_script }} run: ${{ inputs.ucrt64_before_script }}
# Read pyproject.toml
- name: 🔁 Extract configurations from pyproject.toml
id: getVariables
shell: python
run: |
from os import getenv
from pathlib import Path
from sys import version
from textwrap import dedent
print(f"Python: {version}")
from tomli import load as tomli_load
htmlDirectory = Path("htmlcov")
xmlFile = Path("./coverage.xml")
jsonFile = Path("./coverage.json")
coverageRC = "${{ inputs.coverage_config }}".strip()
# Read output paths from 'pyproject.toml' file
if coverageRC == "pyproject.toml":
pyProjectFile = Path("pyproject.toml")
if pyProjectFile.exists():
with pyProjectFile.open("rb") as file:
pyProjectSettings = tomli_load(file)
htmlDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
xmlFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
jsonFile = Path(pyProjectSettings["tool"]["coverage"]["json"]["output"])
else:
print(f"File '{pyProjectFile}' not found.")
print(f"::error title=FileNotFoundError::File '{pyProjectFile}' not found.")
exit(1)
# Read output paths from '.coveragerc' file
elif len(coverageRC) > 0:
coverageRCFile = Path(coverageRC)
if coverageRCFile.exists():
with coverageRCFile.open("rb") as file:
coverageRCSettings = tomli_load(file)
htmlDirectory = Path(coverageRCSettings["html"]["directory"])
xmlFile = Path(coverageRCSettings["xml"]["output"])
jsonFile = Path(coverageRCSettings["json"]["output"])
else:
print(f"File '{coverageRCFile}' not found.")
print(f"::error title=FileNotFoundError::File '{coverageRCFile}' not found.")
exit(1)
# 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"""\
unittest_report_html_directory={htmlDirectory}
coverage_report_html_directory={htmlDirectory.as_posix()}
coverage_report_xml={xmlFile}
coverage_report_json={jsonFile}
"""))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
# Run pytests # Run pytests
- name: ✅ Run unit tests (Ubuntu/macOS) - name: ✅ Run unit tests (Ubuntu/macOS)
@@ -395,12 +347,12 @@ jobs:
export PYTHONPATH=$(pwd) export PYTHONPATH=$(pwd)
cd "${{ inputs.root_directory || '.' }}" cd "${{ inputs.root_directory || '.' }}"
[ -n '${{ inputs.unittest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=report/unit/TestReportSummary.xml' || unset PYTEST_ARGS [ -n '${{ inputs.unittest_xml_artifact }}' ] && PYTEST_ARGS='--junitxml=${{ inputs.unittest_report_xml_directory }}/${{ inputs.unittest_report_xml_filename }}' || unset PYTEST_ARGS
if [ -n '${{ inputs.coverage_config }}' ]; then if [ -n '${{ inputs.coverage_config }}' ]; then
echo "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}" printf "%s\n" "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }} coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
else else
echo "python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}" printf "%s\n" "python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }} python -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
fi fi
@@ -411,7 +363,7 @@ jobs:
$env:PYTHONPATH = (Get-Location).ToString() $env:PYTHONPATH = (Get-Location).ToString()
cd "${{ inputs.root_directory || '.' }}" cd "${{ inputs.root_directory || '.' }}"
$PYTEST_ARGS = if ("${{ inputs.unittest_xml_artifact }}") { "--junitxml=report/unit/TestReportSummary.xml" } else { "" } $PYTEST_ARGS = if ("${{ inputs.unittest_xml_artifact }}") { "--junitxml=${{ inputs.unittest_report_xml_directory }}/${{ inputs.unittest_report_xml_filename }}" } else { "" }
if ("${{ inputs.coverage_config }}") { if ("${{ inputs.coverage_config }}") {
Write-Host "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}" Write-Host "coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }} coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -raP $PYTEST_ARGS --color=yes ${{ inputs.tests_directory || '.' }}/${{ inputs.unittest_directory }}
@@ -434,19 +386,19 @@ jobs:
if: inputs.coverage_html_artifact != '' if: inputs.coverage_html_artifact != ''
continue-on-error: true continue-on-error: true
run: | run: |
coverage html --data-file=.coverage -d ${{ steps.getVariables.outputs.coverage_report_html_directory }} coverage html --data-file=.coverage -d ${{ inputs.coverage_report_html_directory }}
rm ${{ steps.getVariables.outputs.coverage_report_html_directory }}/.gitignore rm ${{ inputs.coverage_report_html_directory }}/.gitignore
# Upload artifacts # Upload artifacts
- name: 📤 Upload 'TestReportSummary.xml' artifact - name: 📤 Upload '${{ inputs.unittest_report_xml_filename }}' artifact
if: inputs.unittest_xml_artifact != '' if: inputs.unittest_xml_artifact != ''
continue-on-error: true continue-on-error: true
uses: pyTooling/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.unittest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.unittest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
working-directory: report/unit working-directory: ${{ inputs.unittest_report_xml_directory }}
path: TestReportSummary.xml path: ${{ inputs.unittest_report_xml_filename }}
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -6,7 +6,7 @@ on:
jobs: jobs:
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
python_version_list: "3.12 3.13" python_version_list: "3.12 3.13"
@@ -22,7 +22,7 @@ jobs:
include: ${{ fromJson(needs.Params.outputs.python_jobs) }} include: ${{ fromJson(needs.Params.outputs.python_jobs) }}
steps: steps:
- name: Content creation for ${{ matrix.system }}-${{ matrix.python }} - name: Content creation for ${{ matrix.system }}-${{ matrix.python }}
run: echo "${{ matrix.runs-on }}-${{ matrix.python }}" >> artifact.txt run: printf "%s\n" "${{ matrix.runs-on }}-${{ matrix.python }}" >> artifact.txt
- name: 📤 Upload artifact for ${{ matrix.system }}-${{ matrix.python }} - name: 📤 Upload artifact for ${{ matrix.system }}-${{ matrix.python }}
uses: pyTooling/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
@@ -39,7 +39,7 @@ jobs:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: Package creation - name: Package creation
run: echo "Package" >> package.txt run: printf "%s\n" "Package" >> package.txt
- name: 📤 Upload artifact for ${{ matrix.system }}-${{ matrix.python }} - name: 📤 Upload artifact for ${{ matrix.system }}-${{ matrix.python }}
uses: pyTooling/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
@@ -50,7 +50,7 @@ jobs:
retention-days: 1 retention-days: 1
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r2 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r4
needs: needs:
- Params - Params
- Testing - Testing

View File

@@ -6,64 +6,62 @@ on:
jobs: jobs:
ConfigParams: ConfigParams:
uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r3 uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@r4
with: with:
package_name: pyDummy package_name: pyDummy
UnitTestingParams: UnitTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r3 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyDummy name: pyDummy
python_version_list: "3.9 3.10 3.11 3.12 3.13 pypy-3.9 pypy-3.10" python_version_list: "3.9 3.10 3.11 3.12 3.13 pypy-3.9 pypy-3.10"
# disable_list: "windows:pypy-3.10" # disable_list: "windows:pypy-3.10"
PlatformTestingParams: PlatformTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r3 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Platform name: Platform
python_version_list: "" python_version_list: ""
system_list: "ubuntu windows macos mingw32 mingw64 clang64 ucrt64" system_list: "ubuntu windows macos mingw64 clang64 ucrt64"
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r3 uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r4
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
with: with:
jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }} jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
unittest_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }} unittest_report_xml_filename: ${{ needs.ConfigParams.outputs.unittest_report_xml_filename }}
# coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} coverage_report_html_directory: ${{ needs.ConfigParams.outputs.coverage_report_html_directory }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
unittest_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
# coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }} # coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
# coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} # coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
# coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }} # coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
PlatformTesting: PlatformTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r3 uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r4
needs: needs:
- ConfigParams
- PlatformTestingParams - PlatformTestingParams
with: with:
jobs: ${{ needs.PlatformTestingParams.outputs.python_jobs }} jobs: ${{ needs.PlatformTestingParams.outputs.python_jobs }}
# tests_directory: "" # tests_directory: ""
unittest_directory: platform unittest_directory: platform
unittest_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }} unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
unittest_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }} unittest_report_xml_filename: ${{ needs.ConfigParams.outputs.unittest_report_xml_filename }}
coverage_sqlite_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }} coverage_report_html_directory: ${{ needs.ConfigParams.outputs.coverage_report_html_directory }}
coverage_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_xml }} unittest_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}
coverage_json_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_json }} unittest_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }}
coverage_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_html }} coverage_sqlite_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }}
coverage_xml_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_xml }}
# Coverage: coverage_json_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_json }}
# uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r3 coverage_html_artifact: ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_html }}
# needs:
# - UnitTestingParams
# with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
# artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
# secrets:
# codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
StaticTypeCheck: StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r3 uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r4
needs: needs:
- ConfigParams - ConfigParams
- UnitTestingParams - UnitTestingParams
@@ -76,7 +74,7 @@ jobs:
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
DocCoverage: DocCoverage:
uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@r1 uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@r4
needs: needs:
- ConfigParams - ConfigParams
- UnitTestingParams - UnitTestingParams
@@ -86,48 +84,48 @@ jobs:
# fail_below: 70 # fail_below: 70
Package: Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@r3 uses: pyTooling/Actions/.github/workflows/Package.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- UnitTesting - UnitTesting
# - Coverage
- PlatformTesting - PlatformTesting
with: with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }} python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
PublishCoverageResults: PublishCoverageResults:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r3 uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- UnitTesting - UnitTesting
- PlatformTesting - PlatformTesting
# - Coverage
with: with:
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }} coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }} coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
secrets: secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }} codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishTestResults: PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r3 uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r4
needs: needs:
- UnitTestingParams
- UnitTesting - UnitTesting
- PlatformTesting - PlatformTesting
with: with:
additional_merge_args: '-d "--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit;reduce-depth:pytest.tests.platform"' additional_merge_args: '-d "--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit;reduce-depth:pytest.tests.platform"'
merged_junit_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
# VerifyDocs: # VerifyDocs:
# uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@r3 # uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@r4
# needs: # needs:
# - UnitTestingParams # - UnitTestingParams
# with: # with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }} # python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
Documentation: Documentation:
uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@r3 uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@r4
needs: needs:
- ConfigParams - ConfigParams
- UnitTestingParams - UnitTestingParams
@@ -137,13 +135,13 @@ jobs:
with: with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }} python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
coverage_report_json_directory: ${{ needs.ConfigParams.outputs.coverage_report_json_directory }} coverage_report_json_directory: ${{ needs.ConfigParams.outputs.coverage_report_json_directory }}
# unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }} unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
# coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }} html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }} latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
IntermediateCleanUp: IntermediateCleanUp:
uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@r1 uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- PublishCoverageResults - PublishCoverageResults
@@ -151,25 +149,24 @@ jobs:
- Documentation - Documentation
with: with:
sqlite_coverage_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}- sqlite_coverage_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}-
xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}- xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-
PDFDocumentation: PDFDocumentation:
uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@r3 uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- Documentation - Documentation
with: with:
document: actions document: Actions
latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }} latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }} pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }}
PublishToGitHubPages: PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r3 uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- Documentation - Documentation
# - PDFDocumentation - PDFDocumentation
# - Coverage
- PublishCoverageResults - PublishCoverageResults
- StaticTypeCheck - StaticTypeCheck
with: with:
@@ -178,18 +175,17 @@ jobs:
typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
ReleasePage: ReleasePage:
uses: pyTooling/Actions/.github/workflows/Release.yml@r3 uses: pyTooling/Actions/.github/workflows/Release.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- UnitTesting - UnitTesting
- PlatformTesting - PlatformTesting
# - Coverage
# - StaticTypeCheck # - StaticTypeCheck
- Package - Package
- PublishToGitHubPages - PublishToGitHubPages
PublishOnPyPI: PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r3 uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- UnitTestingParams - UnitTestingParams
@@ -203,16 +199,15 @@ jobs:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r3 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r4
needs: needs:
- UnitTestingParams - UnitTestingParams
- PlatformTestingParams - PlatformTestingParams
- UnitTesting - UnitTesting
# - Coverage
- StaticTypeCheck - StaticTypeCheck
- PlatformTesting - PlatformTesting
- Documentation - Documentation
# - PDFDocumentation - PDFDocumentation
- PublishTestResults - PublishTestResults
- PublishCoverageResults - PublishCoverageResults
- PublishToGitHubPages - PublishToGitHubPages
@@ -222,7 +217,6 @@ jobs:
remaining: | remaining: |
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}-* ${{ 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_xml }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}-* ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}-*
@@ -234,9 +228,9 @@ jobs:
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }} ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}-* ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_xml }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }}-* ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).unittesting_html }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_sqlite }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_xml }}-* ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_xml }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_json }}-* ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_json }}-*
${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_html }}-* ${{ fromJson(needs.PlatformTestingParams.outputs.artifact_names).codecoverage_html }}-*

View File

@@ -6,7 +6,7 @@ on:
jobs: jobs:
NamespacePackage: NamespacePackage:
uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@r2 uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@r4
with: with:
package_namespace: pyExamples package_namespace: pyExamples
package_name: Extensions package_name: Extensions

View File

@@ -12,9 +12,9 @@ jobs:
steps: steps:
- name: 🖉 Build 1 - name: 🖉 Build 1
run: | run: |
echo "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt printf "%s\n" "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt
echo "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log printf "%s\n" "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log
echo "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log printf "%s\n" "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log
- name: 📤 Upload artifact - name: 📤 Upload artifact
uses: pyTooling/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
@@ -28,8 +28,8 @@ jobs:
- name: 🖉 Program - name: 🖉 Program
run: | run: |
echo "Document other $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt printf "%s\n" "Document other $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt
echo "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > program.py printf "%s\n" "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > program.py
- name: 📤 Upload artifact - name: 📤 Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -42,7 +42,7 @@ jobs:
retention-days: 1 retention-days: 1
NightlyPage: NightlyPage:
uses: pyTooling/Actions/.github/workflows/NightlyRelease.yml@main uses: pyTooling/Actions/.github/workflows/NightlyRelease.yml@r4
needs: needs:
- Build - Build
secrets: inherit secrets: inherit
@@ -56,35 +56,13 @@ jobs:
version=4.2.0 version=4.2.0
tool=myTool tool=myTool
prog=program prog=program
nightly_title: "Nightly Release" nightly_title: "Nightly Test Release"
nightly_description: | nightly_description: |
This *nightly* release contains all latest and important artifacts created by GHDL's CI pipeline. This *nightly* release contains all latest and important artifacts created by %tool%'s CI pipeline.
# GHDL %version% # %tool% %version%
GHDL offers the simulator and synthesis tool for VHDL. GHDL can be build for various backends: * %prog%
* `gcc` - using the GCC compiler framework
* `mcode` - in memory code generation
* `llvm` - using the LLVM compiler framework
* `llvm-jit` - using the LLVM compiler framework, but in memory
The following asset categories are provided for GHDL:
* macOS x64-64 builds as TAR/GZ file
* macOS aarch64 builds as TAR/GZ file
* Ubuntu 24.04 LTS builds as TAR/GZ file
* Windows builds for standalone usage (without MSYS2) as ZIP file
* MSYS2 packages as TAR/ZST file
# pyGHDL %version%
The Python package `pyGHDL` offers Python binding (`pyGHDL.libghdl`) to a `libghdl` shared library (`*.so`/`*.dll`).
In addition to the low-level binding layer, pyGHDL offers:
* a Language Server Protocol (LSP) instance for e.g. live code checking by editors
* a Code Document Object Model (CodeDOM) based on [pyVHDLModel](https://github.com/VHDL/pyVHDLModel)
The following asset categories are provided for pyGHDL:
* Platform specific Python wheel package for Ubuntu incl. `pyGHDL...so`
* Platform specific Python wheel package for Windows incl. `pyGHDL...dll`
assets: | assets: |
document: document1.txt: Documentation document: document1.txt: Documentation
document: build.log: Logfile - %tool% - %tool% document: build.log: Logfile - %tool% - %tool%
@@ -99,3 +77,44 @@ jobs:
document:$archive7.tar.gz: Archive 7 - tar.gz + dir document:$archive7.tar.gz: Archive 7 - tar.gz + dir
document:$archive8.tzst: Archive 8 - tzst + dir document:$archive8.tzst: Archive 8 - tzst + dir
document:$archive9.tar.zst:Archive 9 - tar.zst + dir document:$archive9.tar.zst:Archive 9 - tar.zst + dir
NightlyPageWithInventory:
uses: ./.github/workflows/NightlyRelease.yml
needs:
- Build
secrets: inherit
permissions:
contents: write
actions: write
# attestations: write
with:
replacements: |
version=4.2.0
tool=myTool
prog=program
nightly_name: inventory
nightly_title: "Nightly Test Release with Inventory"
nightly_description: |
This *nightly* release contains all latest and important artifacts created by %tool%'s CI pipeline.
# %tool% %version%
* %prog%
* iventory.json
inventory-json: "inventory.json"
inventory-version: 4.2.5
inventory-categories: "kind1,kind2"
assets: |
document: document1.txt: doc,html: Documentation
document: build.log: build,log: Logfile - %tool% - %tool%
other: document1.txt: build,SBOM:SBOM - %version%
other: %prog%.py: app,binary:Application - %tool% - %version%
document:!archive1.zip: Archive 1 - zip
document:!archive2.tgz: Archive 2 - tgz
document:!archive3.tar.gz: Archive 3 - tar.gz
document:!archive4.tzst: Archive 4 - tzst
document:!archive5.tar.zst: Archive 5 - tar.zst
document:$archive6.tgz: Archive 6 - tgz + dir
document:$archive7.tar.gz: Archive 7 - tar.gz + dir
document:$archive8.tzst: Archive 8 - tzst + dir
document:$archive9.tar.zst: Archive 9 - tar.zst + dir

View File

@@ -6,24 +6,24 @@ on:
jobs: jobs:
Params_Default: Params_Default:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
Params_PythonVersions: Params_PythonVersions:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
python_version_list: "3.11 3.12 pypy-3.9 pypy-3.10" python_version_list: "3.11 3.12 pypy-3.9 pypy-3.10"
Params_Systems: Params_Systems:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
system_list: "windows mingw32 mingw64" system_list: "windows mingw32 mingw64"
Params_Include: Params_Include:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
python_version_list: "3.11" python_version_list: "3.11"
@@ -31,7 +31,7 @@ jobs:
include_list: "ubuntu:3.12 ubuntu:3.13" include_list: "ubuntu:3.12 ubuntu:3.13"
Params_Exclude: Params_Exclude:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
python_version_list: "3.12" python_version_list: "3.12"
@@ -39,7 +39,7 @@ jobs:
exclude_list: "windows:3.12 windows:3.13" exclude_list: "windows:3.12 windows:3.13"
Params_Disable: Params_Disable:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
python_version_list: "3.12" python_version_list: "3.12"
@@ -47,7 +47,7 @@ jobs:
disable_list: "windows:3.12 windows:3.13" disable_list: "windows:3.12 windows:3.13"
Params_All: Params_All:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r2 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: Example name: Example
python_version_list: "3.12 3.13" python_version_list: "3.12 3.13"
@@ -83,7 +83,7 @@ jobs:
expectedPythonVersion = "3.13" expectedPythonVersion = "3.13"
expectedPythons = ["3.9", "3.10", "3.11", "3.12", "3.13"] expectedPythons = ["3.9", "3.10", "3.11", "3.12", "3.13"]
expectedSystems = ["ubuntu", "windows", "macos", "macos-arm"] expectedSystems = ["ubuntu", "windows", "macos", "macos-arm"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["mingw64:3.11", "ucrt64:3.11"] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["mingw64:3.12", "ucrt64:3.11"]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
"unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML", "unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML",
@@ -146,7 +146,7 @@ jobs:
expectedPythonVersion = "3.13" expectedPythonVersion = "3.13"
expectedPythons = ["3.11", "3.12", "pypy-3.9", "pypy-3.10"] expectedPythons = ["3.11", "3.12", "pypy-3.9", "pypy-3.10"]
expectedSystems = ["ubuntu", "windows", "macos", "macos-arm"] expectedSystems = ["ubuntu", "windows", "macos", "macos-arm"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["mingw64:3.11", "ucrt64:3.11"] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["mingw64:3.12", "ucrt64:3.11"]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
"unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML", "unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML",
@@ -209,7 +209,7 @@ jobs:
expectedPythonVersion = "3.13" expectedPythonVersion = "3.13"
expectedPythons = ["3.9", "3.10", "3.11", "3.12", "3.13"] expectedPythons = ["3.9", "3.10", "3.11", "3.12", "3.13"]
expectedSystems = ["windows"] expectedSystems = ["windows"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["mingw32:3.11", "mingw64:3.11"] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["mingw32:3.12", "mingw64:3.11"]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
"unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML", "unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML",

View File

@@ -6,7 +6,7 @@ on:
jobs: jobs:
SimplePackage: SimplePackage:
uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@r2 uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@r4
with: with:
package_name: pyDummy package_name: pyDummy
secrets: secrets:

View File

@@ -30,7 +30,7 @@ jobs:
# This job is a workaround for global variables # This job is a workaround for global variables
# See https://github.com/actions/runner/issues/480 # See https://github.com/actions/runner/issues/480
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@main uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: ToolName name: ToolName
# Optional # Optional
@@ -39,7 +39,7 @@ jobs:
python_version_list: '3.8 3.9 3.10' python_version_list: '3.8 3.9 3.10'
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@main uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r4
needs: needs:
- Params - Params
with: with:
@@ -57,7 +57,7 @@ jobs:
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }} artifact: ${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }}
Coverage: Coverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@main uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r4
needs: needs:
- Params - Params
with: with:
@@ -71,7 +71,7 @@ jobs:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }} codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
StaticTypeCheck: StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@main uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r4
needs: needs:
- Params - Params
with: with:
@@ -87,7 +87,7 @@ jobs:
allow_failure: true allow_failure: true
PublishTestResults: PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@main uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r4
needs: needs:
- UnitTesting - UnitTesting
- StaticTypeCheck - StaticTypeCheck
@@ -96,7 +96,7 @@ jobs:
report_files: artifacts/**/*.xml report_files: artifacts/**/*.xml
Package: Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@main uses: pyTooling/Actions/.github/workflows/Package.yml@r4
needs: needs:
- Params - Params
- Coverage - Coverage
@@ -107,7 +107,7 @@ jobs:
requirements: 'wheel' requirements: 'wheel'
Release: Release:
uses: pyTooling/Actions/.github/workflows/Release.yml@main uses: pyTooling/Actions/.github/workflows/Release.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- UnitTesting - UnitTesting
@@ -116,7 +116,7 @@ jobs:
- Package - Package
PublishOnPyPI: PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@main uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- Params - Params
@@ -131,7 +131,7 @@ jobs:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
VerifyDocs: VerifyDocs:
uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@main uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@r4
needs: needs:
- Params - Params
with: with:
@@ -139,7 +139,7 @@ jobs:
python_version: ${{ needs..Params.outputs.python_version }} python_version: ${{ needs..Params.outputs.python_version }}
BuildTheDocs: BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@main uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r4
needs: needs:
- Params - Params
- VerifyDocs - VerifyDocs
@@ -147,7 +147,7 @@ jobs:
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).documentation_html }} artifact: ${{ fromJson(needs.Params.outputs.artifact_names).documentation_html }}
PublishToGitHubPages: PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@main uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r4
needs: needs:
- Params - Params
- BuildTheDocs - BuildTheDocs
@@ -160,7 +160,7 @@ jobs:
typing: ${{ fromJson(needs.Params.outputs.artifact_names).statictyping_html }} typing: ${{ fromJson(needs.Params.outputs.artifact_names).statictyping_html }}
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@main uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r4
needs: needs:
- Params - Params
- PublishTestResults - PublishTestResults

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

109
README.md
View File

@@ -10,48 +10,93 @@ This repository gathers reusable CI tooling for testing, packaging and distribut
See [GitHub Actions and GitHub Reusable Workflows](https://pytooling.github.io/Actions/Background.html) for more See [GitHub Actions and GitHub Reusable Workflows](https://pytooling.github.io/Actions/Background.html) for more
background information. background information.
## Reusable workflows ## Reusable Actions
- **Artifacts:**
[**pyTooling/upload-artifact**](https://github.com/pyTooling/upload-artifact): The upload-artifact action will
preserve file attributes like permissions.
[**pyTooling/download-artifact**](https://github.com/pyTooling/download-artifact): The download-artifact action will
preserve file attributes like permissions.
## Predefined Docker Images
- **Documentation:**
[**MikTeX**](https://github.com/pyTooling/MikTeX): A predefined MikTeX image based on Debian Bookworm + Python 3.13
with specific tools for documentation generation using e.g. Sphinx and related extensions.
## Reusable Workflows
This repository provides 10+ *Reusable Workflows* based on the CI pipelines of the repos in this GitHub organisation, This repository provides 10+ *Reusable Workflows* based on the CI pipelines of the repos in this GitHub organisation,
[EDA²](https://github.com/edaa-org), [VHDL](https://github.com/vhdl), and others. By combining them, Python packages can [EDA²](https://github.com/edaa-org), [VHDL](https://github.com/vhdl), and others. By combining them, Python packages can
be continuously tested and released along with Sphinx documentation sites, to GitHub Releases, GitHub Pages and PyPI. be continuously tested and released along with Sphinx documentation sites, to GitHub Releases, GitHub Pages and PyPI.
Optionally, coverage and static type check reports can be gathered and integrated into the online documentation. Optionally, coverage and static type check reports can be gathered and integrated into the online documentation.
[![](ExamplePipeline_dark.png)](ExamplePipeline_dark.png) [![](doc/_static/pyTooling-Actions-SimplePackage.png)](doc/_static/pyTooling-Actions-SimplePackage.png)
[![](ExamplePipeline_light.png)](ExamplePipeline_light.png)
As shown in the screenshots above, the expected order is: As shown in the screenshots above, the expected order is:
- Global: - **Global:**
- [Parameters](.github/workflows/Parameters.yml): a workaround for the limitations to handle global variables in [**Parameters**](.github/workflows/Parameters.yml): It generates output parameters with artifact names and job matrices
GitHub Actions workflows (see [actions/runner#480](https://github.com/actions/runner/issues/480)). to be used in later running jobs.
It generates outputs with artifact names and job matrices to be used in later running jobs. It's a workaround for the limitations to handle global variables in GitHub Actions workflows (see
- Code testing/analysis: [actions/runner#480](https://github.com/actions/runner/issues/480)).
- [UnitTesting](.github/workflows/UnitTesting.yml): run unit test with `pytest` using multiple versions of Python, and
optionally upload results as XML reports. Configuration options to `pytest` should be given via section [**ExtractConfiguration**](.github/workflows/ExtractConfiguration.yml): extracts configuration values from
`[tool.pytest.ini_options]` in a `pyproject.toml` file. `pyproject.toml` and exposes configured paths and filenames as job output parameters.
- [CoverageCollection](.github/workflows/CoverageCollection.yml): collect code coverage data (incl. branch coverage) - **Predefined pipelines:**
with `pytest`/`pytest-cov`/`coverage.py` using a single version of Python (latest). It generates HTML and Cobertura [**CompletePipeline**](.github/workflows/CompletePipeline.yml): is a predefined pipeline for typical Python projects
(XML)reports, upload the HTML report as an artifact, and upload the test results to Codecov and Codacy. Configuration using all predefined job templates of pyTooling at once: (unit testing, code coverage, static typing, documentation
options to `pytest` and `coverage.py` should be given via section `[tool.pytest.ini_options]` and `[tool.coverage.*]` report generation and publishing, packaging, releasing, ...)
in a `pyproject.toml` file. - **Code testing/analysis:**
- [StaticTypeCheck](.github/workflows/StaticTypeCheck.yml): collect static type check result with `mypy`, and [**ApplicationTesting**](.github/workflows/ApplicationTesting.yml): like UnitTesting, but running tests using an
optionally upload results as an HTML report. installed Python package.
Example `commands`:
[**UnitTesting**](.github/workflows/UnitTesting.yml): run unit test with `pytest` using multiple versions of Python, and
optionally upload results as XML reports. Configuration options to `pytest` should be given via section
`[tool.pytest.ini_options]` in a `pyproject.toml` file.
Besides test results, also code coverage data (incl. branch coverage) can be collected using
`pytest`/`pytest-cov`/`coverage.py`. Configuration options to `coverage.py` should be given via section
`[tool.coverage.*]` in a `pyproject.toml` file.
While multiple report formats can be created in the job, it's recommended to use `PublishTestResults` and/or
`PublishCoverageResults` to merge results from matrix runs and then generate final reports as XML, JSON or HTML.
Finally, reports can be published to GitHub Pages or cloud services like Codecov and Codacy.
[**StaticTypeCheck**](.github/workflows/StaticTypeCheck.yml): collect static type check result with `mypy`, and
optionally upload results as an HTML report.
[**VerifyDocs**](.github/workflows/VerifyDocs.yml): extract code examples from the README and test these code snippets.
- **Packaging and releasing:**
[**Package**](.github/workflows/Package.yml): generate source and wheel packages, and upload them as an artifact.
[**PublishOnPyPI**](.github/workflows/PublishOnPyPI.yml): publish source and wheel packages to PyPI.
[**PublishTestResults**](.github/workflows/PublishTestResults.yml): publish unit test results through GH action `dorny/test-reporter`.
[**PublishCoverageResults**](.github/workflows/PublishCoverageResults.yml): publish ucode coverage results.
[**NightlyRelease**](.github/workflows/NightlyRelease.yml): publish GitHub Release.
[**Release**](.github/workflows/Release.yml): publish GitHub Release.
- **Documentation:**
[**SphinxDocumentation**](.github/workflows/PublishCoverageResults.yml): create HTML and LaTeX documentation using
Sphinx.
[**LaTeXDocumentation**](.github/workflows/LaTeXDocumentation.yml): compile LaTeX documentation to a PDF file using
MikTeX.
[**PublishToGitHubPages**](.github/workflows/PublishToGitHubPages.yml): publish HTML documentation to GitHub Pages.
- **Cleanup:**
[**IntermediateCleanUp**](.github/workflows/IntermediateCleanUp.yml): delete intermediate artifacts.
[**ArtifactCleanUp**](.github/workflows/ArtifactCleanUp.yml): delete artifacts.
- **⚠ Deprecated ⚠:**
[**CoverageCollection**](.github/workflows/CoverageCollection.yml): Use `UnitTesting`, because is can collect code
coverage too. This avoids code duplication in job templates.
[**BuildTheDocs**](.github/workflows/BuildTheDocs.yml): Use `SphinxDocumentation`, `LaTeXDocumentation` and
`PublishToGitHubPages`. BuildTheDocs isn't maintained anymore.
- [VerifyDocs](.github/workflows/VerifyDocs.yml): extract code examples from the README and test these code snippets.
- Packaging and releasing:
- [Release](.github/workflows/Release.yml): publish GitHub Release.
- [Package](.github/workflows/Package.yml): generate source and wheel packages, and upload them as an artifact.
- [PublishOnPyPI](.github/workflows/PublishOnPyPI.yml): publish source and wheel packages to PyPI.
- [PublishTestResults](.github/workflows/PublishTestResults.yml): publish unit test results through GH action `dorny/test-reporter`.
- Documentation:
- [BuildTheDocs](.github/workflows/BuildTheDocs.yml): build Sphinx documentation with BuildTheDocs, and upload HTML as
an artifact.
- [PublishToGitHubPages](.github/workflows/PublishToGitHubPages.yml): publish HTML documentation to GitHub Pages.
- Cleanup:
- [ArtifactCleanUp](.github/workflows/ArtifactCleanUp.yml): delete artifacts.
### Example pipeline ### Example pipeline

View File

@@ -1,2 +1,2 @@
wheel ~= 0.45 wheel ~= 0.45
twine ~= 5.1 twine ~= 6.0

View File

@@ -95,7 +95,7 @@ The following block shows a minimal YAML workflow file:
# Update tag and pre-release # Update tag and pre-release
# - Update (force-push) tag to the commit that is used in the workflow. # - Update (force-push) tag to the commit that is used in the workflow.
# - Upload artifacts defined by the user. # - Upload artifacts defined by the user.
- uses: pyTooling/Actions/releaser@r0 - uses: pyTooling/Actions/releaser@r4
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
files: | files: |

View File

@@ -60,12 +60,12 @@ Documentation Only (Sphinx)
jobs: jobs:
BuildTheDocs: BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r0 uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r4
with: with:
artifact: Documentation artifact: Documentation
PublishToGitHubPages: PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r4
needs: needs:
- BuildTheDocs - BuildTheDocs
with: with:

View File

@@ -27,7 +27,7 @@ The simplest variant just uses the artifact name for the package.
jobs: jobs:
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r0 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r4
with: with:
package: Package package: Package
@@ -39,7 +39,7 @@ Complex Example
jobs: jobs:
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r0 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r4
needs: needs:
- Params - Params
- UnitTesting - UnitTesting

View File

@@ -30,7 +30,7 @@ Simple Example
jobs: jobs:
BuildTheDocs: BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r0 uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r4
Complex Example Complex Example
@@ -40,7 +40,7 @@ Complex Example
jobs: jobs:
BuildTheDocs: BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r0 uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r4
needs: needs:
- Params - Params
with: with:

View File

@@ -52,7 +52,7 @@ Simple Example
jobs: jobs:
Coverage: Coverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r0 uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r4
with: with:
artifact: Coverage artifact: Coverage
secrets: secrets:
@@ -65,7 +65,7 @@ Complex Example
jobs: jobs:
Coverage: Coverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r0 uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r4
needs: needs:
- Params - Params
with: with:

View File

@@ -33,7 +33,7 @@ Simple Example
jobs: jobs:
Package: Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@r0 uses: pyTooling/Actions/.github/workflows/Package.yml@r4
with: with:
artifact: Package artifact: Package
@@ -45,7 +45,7 @@ Complex Example
jobs: jobs:
Package: Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@r0 uses: pyTooling/Actions/.github/workflows/Package.yml@r4
needs: needs:
- Params - Params
- Coverage - Coverage

View File

@@ -35,7 +35,7 @@ requires a `name` parameter to create the artifact names.
jobs: jobs:
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
@@ -81,7 +81,7 @@ over resulting in the following combinations:
jobs: jobs:
UnitTestingParams: UnitTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
python_version_list: "3.8 3.9 3.10 3.11 pypy-3.9 pypy-3.10" python_version_list: "3.8 3.9 3.10 3.11 pypy-3.9 pypy-3.10"
@@ -89,14 +89,14 @@ over resulting in the following combinations:
exclude_list: "windows:pypy-3.9 windows:pypy-3.10" exclude_list: "windows:pypy-3.9 windows:pypy-3.10"
PerformanceTestingParams: PerformanceTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
python_version_list: "3.11 3.12" python_version_list: "3.11 3.12"
system_list: "ubuntu windows macos" system_list: "ubuntu windows macos"
PlatformTestingParams: PlatformTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@dev uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
python_version_list: "3.12" python_version_list: "3.12"
@@ -297,12 +297,12 @@ variables. Thus, this job is used to compute an output parameter that can be reu
jobs: jobs:
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
CodeCoverage: CodeCoverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r0 uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r4
needs: needs:
- Params - Params
with: with:
@@ -330,12 +330,12 @@ A job description contains the following key-value pairs:
jobs: jobs:
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@dev uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r4
needs: needs:
- Params - Params
with: with:
@@ -389,12 +389,12 @@ The supported artifacts are:
jobs: jobs:
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r0 uses: pyTooling/Actions/.github/workflows/Parameters.yml@r4
with: with:
name: pyTooling name: pyTooling
Coverage: Coverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@dev uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@r4
needs: needs:
- Params - Params
with: with:

View File

@@ -42,7 +42,7 @@ by a Git tag. A secret is forwarded from GitHub secrets to a job secret.
# ... # ...
PublishOnPyPI: PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
with: with:
artifact: Package artifact: Package
@@ -66,7 +66,7 @@ by that job. Finally, the list of requirements is overwritten to load a list of
# ... # ...
PublishOnPyPI: PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- Params - Params

View File

@@ -34,7 +34,7 @@ Simple Example
jobs: jobs:
PublishTestResults: PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r4
Complex Example Complex Example
=============== ===============
@@ -49,7 +49,7 @@ Complex Example
# ... # ...
PublishTestResults: PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@r4
needs: needs:
- CodeCoverage - CodeCoverage
- UnitTesting - UnitTesting

View File

@@ -29,7 +29,7 @@ Simple Example
# ... # ...
PublishToGitHubPages: PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r4
needs: needs:
- BuildTheDocs - BuildTheDocs
with: with:
@@ -43,7 +43,7 @@ Complex Example
jobs: jobs:
PublishToGitHubPages: PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r0 uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r4
needs: needs:
- Params - Params
- BuildTheDocs - BuildTheDocs

View File

@@ -62,7 +62,7 @@ Simple Example
jobs: jobs:
Release: Release:
uses: pyTooling/Actions/.github/workflows/Release.yml@r0 uses: pyTooling/Actions/.github/workflows/Release.yml@r4
Complex Example Complex Example
@@ -72,7 +72,7 @@ Complex Example
jobs: jobs:
Release: Release:
uses: pyTooling/Actions/.github/workflows/Release.yml@r0 uses: pyTooling/Actions/.github/workflows/Release.yml@r4
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- Package - Package

View File

@@ -29,7 +29,7 @@ Simple Example
jobs: jobs:
StaticTypeCheck: StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r0 uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r4
with: with:
commands: | commands: |
touch pyTooling/__init__.py touch pyTooling/__init__.py
@@ -44,7 +44,7 @@ Complex Example
jobs: jobs:
StaticTypeCheck: StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r0 uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@r4
needs: needs:
- Params - Params
with: with:

View File

@@ -36,7 +36,7 @@ Simple Example
# ... # ...
UnitTesting: UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r0 uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@r4
needs: needs:
- Params - Params
with: with:

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

View File

@@ -11,7 +11,7 @@ docutils_stubs ~= 0.0.22
sphinx_rtd_theme ~= 3.0 sphinx_rtd_theme ~= 3.0
# Sphinx Extenstions # Sphinx Extenstions
sphinxcontrib-mermaid>=0.9.2 sphinxcontrib-mermaid ~= 1.0
autoapi >= 2.0.1 autoapi >= 2.0.1
sphinx_design ~= 0.6.1 sphinx_design ~= 0.6.1
sphinx-copybutton >= 0.5.2 sphinx-copybutton >= 0.5.2

View File

@@ -4,11 +4,11 @@
# percent encoding so that the URL is properly parsed. # percent encoding so that the URL is properly parsed.
.. # Sourcecode link to GitHub .. # Sourcecode link to GitHub
.. |SHIELD:svg:pyTooling-github| image:: https://img.shields.io/badge/pyTooling-Actions-63bf7f.svg?longCache=true&style=flat-square&longCache=true&logo=GitHub .. |SHIELD:svg:pyTooling-github| image:: https://img.shields.io/badge/pyTooling-Actions-63bf7f?longCache=true&style=flat-square&longCache=true&logo=GitHub
:alt: Sourcecode on GitHub :alt: Sourcecode on GitHub
:height: 22 :height: 22
:target: https://GitHub.com/pyTooling/Actions :target: https://GitHub.com/pyTooling/Actions
.. |SHIELD:png:pyTooling-github| image:: https://raster.shields.io/badge/pyTooling-Actions-63bf7f.svg?longCache=true&style=flat-square&longCache=true&logo=GitHub .. |SHIELD:png:pyTooling-github| image:: https://raster.shields.io/badge/pyTooling-Actions-63bf7f?longCache=true&style=flat-square&longCache=true&logo=GitHub
:alt: Sourcecode on GitHub :alt: Sourcecode on GitHub
:height: 22 :height: 22
:target: https://GitHub.com/pyTooling/Actions :target: https://GitHub.com/pyTooling/Actions
@@ -18,7 +18,7 @@
:alt: Code license :alt: Code license
:height: 22 :height: 22
:target: Code-License.html :target: Code-License.html
.. |SHIELD:png:pyTooling-src-license| image:: https://img.shields.io/pypi/l/pyTooling?longCache=true&style=flat-square&logo=Apache&label=code .. |SHIELD:png:pyTooling-src-license| image:: https://raster.shields.io/pypi/l/pyTooling?longCache=true&style=flat-square&logo=Apache&label=code
:alt: Code license :alt: Code license
:height: 22 :height: 22
:target: https://GitHub.com/pyTooling/Actions/blob/main/LICENSE.md :target: https://GitHub.com/pyTooling/Actions/blob/main/LICENSE.md
@@ -64,11 +64,11 @@
:target: https://pyTooling.github.io/pyTooling/ :target: https://pyTooling.github.io/pyTooling/
.. # Gitter .. # Gitter
.. |SHIELD:svg:pyTooling-gitter| image:: https://img.shields.io/badge/chat-on%20gitter-4db797.svg?longCache=true&style=flat-square&logo=gitter&logoColor=e8ecef .. |SHIELD:svg:pyTooling-gitter| image:: https://img.shields.io/badge/chat-on%20gitter-4db797.?longCache=true&style=flat-square&logo=gitter&logoColor=e8ecef
:alt: Documentation License :alt: Documentation License
:height: 22 :height: 22
:target: https://gitter.im/hdl/community :target: https://gitter.im/hdl/community
.. |SHIELD:png:pyTooling-gitter| image:: https://raster.shields.io/badge/chat-on%20gitter-4db797.svg?longCache=true&style=flat-square&logo=gitter&logoColor=e8ecef .. |SHIELD:png:pyTooling-gitter| image:: https://raster.shields.io/badge/chat-on%20gitter-4db797.?longCache=true&style=flat-square&logo=gitter&logoColor=e8ecef
:alt: Documentation License :alt: Documentation License
:height: 22 :height: 22
:target: https://gitter.im/hdl/community :target: https://gitter.im/hdl/community

View File

@@ -20,6 +20,9 @@ show_error_codes = true
namespace_packages = true namespace_packages = true
html_report = "report/typing" html_report = "report/typing"
[tool.pytest]
junit_xml = "report/unit/TestReportSummary.xml"
[tool.pytest.ini_options] [tool.pytest.ini_options]
addopts = "--tb=native" addopts = "--tb=native"
# Don't set 'python_classes = *' otherwise, pytest doesn't search for classes # Don't set 'python_classes = *' otherwise, pytest doesn't search for classes
@@ -30,6 +33,7 @@ filterwarnings = [
"error::DeprecationWarning", "error::DeprecationWarning",
"error::PendingDeprecationWarning" "error::PendingDeprecationWarning"
] ]
junit_logging = "all"
[tool.interrogate] [tool.interrogate]
color = true color = true

View File

@@ -88,7 +88,7 @@ if ($build)
rm -Force .\build\bdist.win-amd64 rm -Force .\build\bdist.win-amd64
rm -Force .\build\lib rm -Force .\build\lib
Write-Host -ForegroundColor Yellow "[live][BUILD] Building $PackageName package as wheel ..." Write-Host -ForegroundColor Yellow "[live][BUILD] Building $PackageName package as wheel ..."
py -3.12 -m build --wheel py -3.13 -m build --wheel
Write-Host -ForegroundColor Yellow "[live][BUILD] Building wheel finished" Write-Host -ForegroundColor Yellow "[live][BUILD] Building wheel finished"
} }
@@ -102,9 +102,9 @@ if ($install)
} }
else else
{ Write-Host -ForegroundColor Cyan "[ADMIN][UNINSTALL] Uninstalling $PackageName ..." { Write-Host -ForegroundColor Cyan "[ADMIN][UNINSTALL] Uninstalling $PackageName ..."
py -3.12 -m pip uninstall -y $PackageName py -3.13 -m pip uninstall -y $PackageName
Write-Host -ForegroundColor Cyan "[ADMIN][INSTALL] Installing $PackageName from wheel ..." Write-Host -ForegroundColor Cyan "[ADMIN][INSTALL] Installing $PackageName from wheel ..."
py -3.12 -m pip install .\dist\$PackageName-6.7.0-py3-none-any.whl py -3.13 -m pip install .\dist\$PackageName-8.1.0-py3-none-any.whl
Write-Host -ForegroundColor Cyan "[ADMIN][INSTALL] Closing window in 5 seconds ..." Write-Host -ForegroundColor Cyan "[ADMIN][INSTALL] Closing window in 5 seconds ..."
Start-Sleep -Seconds 5 Start-Sleep -Seconds 5