Compare commits

...

88 Commits

Author SHA1 Message Date
Patrick Lehmann
42e17fae05 v4.2.2 2025-03-07 21:12:53 +01:00
Patrick Lehmann
9b7032a585 Use doc_directory instead of hard-coded paths for workarounds. 2025-03-07 21:02:00 +01:00
Patrick Lehmann
9110c85738 Do not require 'coverage_report_json_directory' in SphinxDocumentation.yml. 2025-03-07 21:01:29 +01:00
Patrick Lehmann
c81d139080 v4.2.1 2025-03-02 15:55:14 +01:00
Patrick Lehmann
c64e054bcd Allow comments in the list of assets. 2025-03-02 11:30:32 +01:00
Patrick Lehmann
78fdb584aa v4.2.0 2025-02-28 22:59:27 +01:00
Patrick Lehmann
a456635686 Increment on errors. 2025-02-28 22:43:49 +01:00
Patrick Lehmann
befc59f22d Fixed check for previous errors. 2025-02-28 22:40:25 +01:00
Patrick Lehmann
d6fc0efd47 Improved indentation for error messages. 2025-02-28 22:39:47 +01:00
Patrick Lehmann
c018acc3c1 Bumped dependencies and fixed Bash coding style. 2025-02-26 18:19:37 +01:00
Patrick Lehmann
d74c610bb4 Fixed Bash syntax. 2025-02-21 00:10:27 +01:00
Patrick Lehmann
edc4ab3e86 Bumped copyright year to 2025. 2025-02-21 00:10:10 +01:00
Patrick Lehmann
0a338ae8b7 Fixed badge URLS. 2025-01-25 21:59:55 +01:00
Patrick Lehmann
4069da0a74 Bumped dependencies. 2025-01-25 21:59:34 +01:00
Patrick Lehmann
679ec24c80 v4.1.0 2025-01-16 21:50:03 +01:00
Patrick Lehmann
3a13486ea6 Add only filename to the inventory. 2025-01-16 19:04:47 +01:00
Patrick Lehmann
34fb9c9869 Coding style fixes. 2025-01-15 23:25:32 +01:00
Patrick Lehmann
7523c4adca Search only for xml files. 2025-01-15 16:09:19 +01:00
Patrick Lehmann
530ad7a4a1 Added timezone. 2025-01-15 16:09:04 +01:00
Patrick Lehmann
bd3f2afaf3 Group output from zip. 2025-01-15 13:08:08 +01:00
Patrick Lehmann
b1e4cb961f v4.0.1 2025-01-14 21:16:37 +01:00
Patrick Lehmann
1e6b71e87b Fixed delimiter sign for category splitting at ','. 2025-01-14 21:07:41 +01:00
Patrick Lehmann
5d8a608893 v4.0.0 2025-01-14 17:03:38 +01:00
Patrick Lehmann
c3b7b3ca64 Take inventory categories from input parameter. 2025-01-14 16:58:21 +01:00
Patrick Lehmann
f61b77ee72 Adding support for a JSON inventory. 2025-01-14 12:17:50 +01:00
Patrick Lehmann
5f18024dd4 Updated pipeline image. 2024-12-27 00:00:02 +01:00
Patrick Lehmann
d0f07e1af4 Fixed printf. 2024-12-26 21:56:04 +01:00
Patrick Lehmann
2b5a9bdeff Updated README. 2024-12-26 19:00:45 +01:00
Patrick Lehmann
d324bdacee Improved handling of true values from GitHub YAML. 2024-12-26 18:12:47 +01:00
Patrick Lehmann
9296bd6e7d Workaround 1 - missing file extensions. 2024-12-24 18:19:14 +01:00
Patrick Lehmann
c37f727e2d Workaround 2 - % sign in a filename. 2024-12-24 13:09:02 +01:00
Patrick Lehmann
a4559e8e63 Build documentation using pyTooling/MikTeX. 2024-12-21 23:51:14 +01:00
Patrick Lehmann
bc94fba95e Fixed broken pipeline dependency. 2024-12-19 00:31:17 +01:00
Patrick Lehmann
d6ec94fea7 Handover coverage_report_html_directory. 2024-12-19 00:23:40 +01:00
Patrick Lehmann
4bc4ec5cf4 Generate merged unit test report. 2024-12-19 00:03:06 +01:00
Patrick Lehmann
e21f89670a Improved usage of tree command. 2024-12-18 23:45:28 +01:00
Patrick Lehmann
c13dd2521c Install interrogate with png extras to avoid error. 2024-12-18 22:50:25 +01:00
Patrick Lehmann
cf2e89a622 Updated Python version for MSYS2 to 3.12. 2024-12-18 22:50:02 +01:00
Patrick Lehmann
a9a3c400fd Create unittest XML and coverage sqlite artifacts in job template test. 2024-12-18 22:49:28 +01:00
Patrick Lehmann
970b4ae021 Reoved commented out Coverage job. 2024-12-18 22:48:45 +01:00
Patrick Lehmann
1807741b0a Fixed TOML key. 2024-12-18 22:29:00 +01:00
Patrick Lehmann
cf095afe77 Fixed usage of true. 2024-12-18 22:24:10 +01:00
Patrick Lehmann
12991ee38a Implemented 'unittest_report_xml_directory' and 'unittest_report_xml_filename'. 2024-12-18 22:23:43 +01:00
Patrick Lehmann
70134b31c3 Exchanged 'echo' with 'printf'.
co-authored-by: Sven Köhler <sven.koehler@gmail.com>
2024-12-16 23:55:20 +01:00
Patrick Lehmann
38514a9005 Create tar files with userid=0 and groupid=0. 2024-12-11 01:15:01 +01:00
Patrick Lehmann
9ceefdbf5d v3.1.1 2024-12-08 23:44:56 +01:00
Patrick Lehmann
b1bc6e50a3 Remove temporary tarball. 2024-12-08 23:41:26 +01:00
Patrick Lehmann
fdee9e011f v3.1.0 2024-12-08 21:27:59 +01:00
Patrick Lehmann
3e50c2ed5b Support embedded tarballs for nightly release's artifacts. 2024-12-08 21:23:55 +01:00
Patrick Lehmann
9e0b1c69f1 v3.0.0 2024-12-08 09:43:32 +01:00
Patrick Lehmann
f084e02f01 Use pattern to reduce the number of downloaded artifacts. 2024-12-07 23:41:16 +01:00
Patrick Lehmann
c34d4e240e [Dependabot]: Bump codecov/codecov-action from 3 to 5 2024-12-07 15:03:03 +01:00
Patrick Lehmann
6d04009bd6 Use new pyTooling/upload-artifact pyTooling/download-artifact composite actions. 2024-12-07 10:20:00 +01:00
Patrick Lehmann
50d32d1950 Replace also in description text. 2024-12-02 08:27:34 +01:00
Patrick Lehmann
7733e8998f Supporting replacements in NightlyReleases. 2024-12-01 22:06:18 +01:00
Patrick Lehmann
4c28b9d003 Added support for ZStandard. [skip ci] 2024-11-29 01:51:56 +01:00
Patrick Lehmann
bafea7d082 Trim leading whitespace. 2024-11-27 19:45:24 +01:00
Patrick Lehmann
9ca7b04f37 Added tar/gz compression as tgz files. 2024-11-27 19:34:44 +01:00
Patrick Lehmann
7a0ee75fd5 Added nightly release job template. 2024-11-27 08:03:57 +01:00
Patrick Lehmann
bc876f7171 Allow disabling the publishing of test reports via Dorny Test Reporter. 2024-11-22 22:23:18 +01:00
Patrick Lehmann
edca070047 Also checkout submodules. 2024-11-17 01:59:51 +01:00
dependabot[bot]
21c2f48dad [Dependabot]: Bump codecov/codecov-action from 3 to 5
Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-15 03:35:36 +00:00
Patrick Lehmann
9338fbd106 v2.0.1 2024-11-10 21:15:14 +01:00
Patrick Lehmann
6869d0f666 Forward secrets to pipeline template. 2024-11-10 21:11:14 +01:00
Patrick Lehmann
bef77effcb v2.1.0 2024-11-10 19:03:51 +01:00
Patrick Lehmann
9808b6c7f9 Handle simple packages and namespace packages by pipeline template.
Added pipeline to check pipeline templates.
2024-11-10 18:49:33 +01:00
Patrick Lehmann
e7e95b446d v2.0.0 2024-11-10 11:18:28 +01:00
Patrick Lehmann
df0889b86b Bumped dependencies. 2024-11-10 11:04:46 +01:00
Patrick Lehmann
87978fd1f6 Added a full pipeline flow for a namespace package. 2024-11-04 07:26:23 +01:00
Patrick Lehmann
3e95c89362 Sphinx Documentation 2024-11-03 14:07:34 +01:00
Patrick Lehmann
f737b07992 Prepare for merge. [skip ci] 2024-11-03 14:05:53 +01:00
Patrick Lehmann
77a6b4c00a Use new extract job. 2024-11-03 13:52:04 +01:00
Patrick Lehmann
ef5c852097 Fixed pipeline dependencies. 2024-11-03 09:20:22 +01:00
Patrick Lehmann
bec076bd66 Fixed pipeline syntax. 2024-11-03 09:07:27 +01:00
Patrick Lehmann
c924651632 Split Sphinx into a prepare and two working sub-jobs for HTML and LaTeX. 2024-11-03 08:43:49 +01:00
Patrick Lehmann
b9b9b0b1d4 Added ubuntu_image_version parameter. 2024-11-03 08:41:51 +01:00
Patrick Lehmann
1cef082753 Bumped dependencies. 2024-10-27 19:47:04 +01:00
Patrick Lehmann
c3a999c754 Using Python 3.12 is good enough.
(cherry picked from commit 9fd7134989)
2024-10-24 22:45:38 +02:00
Patrick Lehmann
9760023567 Adding Python 3.13 support 2024-10-24 22:37:42 +02:00
Patrick Lehmann
fbbb39046a Preparation before merge. [skip ci] 2024-10-24 22:37:13 +02:00
Patrick Lehmann
1d0c8b36e8 Switch from BTD to Sphinx. 2024-10-24 22:29:43 +02:00
Patrick Lehmann
c9d0e8e9c6 Replacing BuildTheDocs. 2024-10-23 00:04:31 +02:00
Patrick Lehmann
00269cf507 Added Support for Python 3.13 and 3.14 (alpha) and removed 3.8. 2024-10-22 07:56:49 +02:00
Patrick Lehmann
a15499a807 After merging pyTest-JUnit XML files, write again the pyTest-jUnit format. 2024-10-14 01:07:44 +02:00
Patrick Lehmann
13076012dd Handle docstr_coverage and pyyaml. 2024-10-10 08:00:51 +02:00
Patrick Lehmann
b2ac6bc0d9 Run also macos-arm. 2024-09-29 03:49:05 +02:00
Patrick Lehmann
e88aa7b973 Set image for macOS x86-64 to macOS-13. 2024-09-29 02:37:19 +02:00
Patrick Lehmann
855d432978 Renamed arm64 to aarch64. 2024-09-29 02:19:59 +02:00
59 changed files with 2598 additions and 742 deletions

View File

@@ -1,9 +0,0 @@
input: doc
output: _build
requirements: requirements.txt
target: gh-pages
formats: [ html ]
images:
base: btdi/sphinx:pytooling
latex: btdi/latex
theme: https://codeload.GitHub.com/buildthedocs/sphinx.theme/tar.gz/v1

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

@@ -89,7 +89,7 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: 📥 Download artifacts '${{ inputs.wheel }}' from 'Package' job - name: 📥 Download artifacts '${{ inputs.wheel }}' from 'Package' job
uses: actions/download-artifact@v4 uses: pyTooling/download-artifact@v4
with: with:
name: ${{ inputs.wheel }} name: ${{ inputs.wheel }}
path: install path: install
@@ -188,8 +188,8 @@ jobs:
f.write(f"pacboy_packages={' '.join(pacboyPackages)}\n") f.write(f"pacboy_packages={' '.join(pacboyPackages)}\n")
- name: '🟦 Setup MSYS2 for ${{ matrix.runtime }}' - name: '🟦 Setup MSYS2 for ${{ matrix.runtime }}'
if: matrix.system == 'msys2'
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
if: matrix.system == 'msys2'
with: with:
msystem: ${{ matrix.runtime }} msystem: ${{ matrix.runtime }}
update: true update: true
@@ -198,8 +198,8 @@ jobs:
${{ inputs.pacboy }} ${{ inputs.pacboy }}
- name: 🐍 Setup Python ${{ matrix.python }} - name: 🐍 Setup Python ${{ matrix.python }}
if: matrix.system != 'msys2'
uses: actions/setup-python@v5 uses: actions/setup-python@v5
if: matrix.system != 'msys2'
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
@@ -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
@@ -255,9 +255,10 @@ jobs:
- name: 📤 Upload 'TestReportSummary.xml' artifact - name: 📤 Upload 'TestReportSummary.xml' artifact
if: inputs.apptest_xml_artifact != '' if: inputs.apptest_xml_artifact != ''
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.apptest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.apptest_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: report/unit/TestReportSummary.xml working-directory: report/unit
path: TestReportSummary.xml
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -25,6 +25,11 @@ name: ArtifactCleanUp
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
package: package:
description: 'Artifacts to be removed on not tagged runs.' description: 'Artifacts to be removed on not tagged runs.'
required: true required: true
@@ -38,17 +43,17 @@ on:
jobs: jobs:
ArtifactCleanUp: ArtifactCleanUp:
name: 🗑️ Artifact Cleanup name: 🗑️ Artifact Cleanup
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: 🗑️ Delete package Artifacts - name: 🗑️ Delete package Artifacts
if: ${{ ! startsWith(github.ref, 'refs/tags') }}
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v5
if: ${{ ! startsWith(github.ref, 'refs/tags') }}
with: with:
name: ${{ inputs.package }} name: ${{ inputs.package }}
- name: 🗑️ Delete remaining Artifacts - name: 🗑️ Delete remaining Artifacts
if: ${{ inputs.remaining != '' }}
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v5
if: ${{ inputs.remaining != '' }}
with: with:
name: ${{ inputs.remaining }} name: ${{ inputs.remaining }}

View File

@@ -37,6 +37,9 @@ jobs:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
steps: steps:
- name: '❗ Deprecation message'
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
@@ -46,11 +49,12 @@ jobs:
skip-deploy: true skip-deploy: true
- name: 📤 Upload 'documentation' artifacts - name: 📤 Upload 'documentation' artifacts
uses: pyTooling/upload-artifact@v4
if: inputs.artifact != '' if: inputs.artifact != ''
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.artifact }} name: ${{ inputs.artifact }}
path: doc/_build/html working-directory: doc/_build/html
path: '*'
retention-days: 1 retention-days: 1
- name: '📓 Publish site to GitHub Pages' - name: '📓 Publish site to GitHub Pages'

View File

@@ -24,6 +24,11 @@ name: Check Documentation
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -42,7 +47,7 @@ on:
jobs: jobs:
DocCoverage: DocCoverage:
name: 👀 Check documentation coverage name: 👀 Check documentation coverage
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -54,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 }})"

323
.github/workflows/CompletePipeline.yml vendored Normal file
View File

@@ -0,0 +1,323 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
name: Namespace Package
on:
workflow_call:
inputs:
package_namespace:
description: 'Name of the tool''s namespace.'
required: false
default: ''
type: string
package_name:
description: 'Name of the tool''s package.'
required: true
type: string
unittest_python_version:
description: 'Python version.'
required: false
default: '3.13'
type: string
unittest_python_version_list:
description: 'Space separated list of Python versions to run tests with.'
required: false
default: '3.9 3.10 3.11 3.12 3.13'
type: string
unittest_system_list:
description: 'Space separated list of systems to run tests on.'
required: false
default: 'ubuntu windows macos macos-arm mingw64 ucrt64'
type: string
unittest_include_list:
description: 'Space separated list of system:python items to be included into the list of test.'
required: false
default: ''
type: string
unittest_exclude_list:
description: 'Space separated list of system:python items to be excluded from the list of test.'
required: false
default: ''
type: string
unittest_disable_list:
description: 'Space separated list of system:python items to be disabled from the list of test.'
required: false
default: ''
type: string
apptest_python_version:
description: 'Python version.'
required: false
default: '3.13'
type: string
apptest_python_version_list:
description: 'Space separated list of Python versions to run tests with.'
required: false
default: ""
type: string
apptest_system_list:
description: 'Space separated list of systems to run tests on.'
required: false
default: 'ubuntu windows macos macos-arm ucrt64'
type: string
apptest_include_list:
description: 'Space separated list of system:python items to be included into the list of test.'
required: false
default: ''
type: string
apptest_exclude_list:
description: 'Space separated list of system:python items to be excluded from the list of test.'
required: false
default: ''
type: string
apptest_disable_list:
description: 'Space separated list of system:python items to be disabled from the list of test.'
required: false
default: ''
type: string
secrets:
PYPI_TOKEN:
description: "Token for pushing releases to PyPI."
required: false
CODACY_PROJECT_TOKEN:
description: "Token for pushing coverage results to Codacy."
required: false
jobs:
ConfigParams:
uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@main
with:
package_namespace: ${{ inputs.package_namespace }}
package_name: ${{ inputs.package_name }}
UnitTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with:
package_namespace: ${{ inputs.package_namespace }}
package_name: ${{ inputs.package_name }}
python_version: ${{ inputs.unittest_python_version }}
python_version_list: ${{ inputs.unittest_python_version_list }}
system_list: ${{ inputs.unittest_system_list }}
include_list: ${{ inputs.unittest_include_list }}
exclude_list: ${{ inputs.unittest_exclude_list }}
disable_list: ${{ inputs.unittest_disable_list }}
AppTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with:
package_namespace: ${{ inputs.package_namespace }}
package_name: ${{ inputs.package_name }}
python_version: ${{ inputs.apptest_python_version }}
python_version_list: ${{ inputs.apptest_python_version_list }}
system_list: ${{ inputs.apptest_system_list }}
include_list: ${{ inputs.apptest_include_list }}
exclude_list: ${{ inputs.apptest_exclude_list }}
disable_list: ${{ inputs.apptest_disable_list }}
UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@main
needs:
- ConfigParams
- UnitTestingParams
with:
jobs: ${{ needs.UnitTestingParams.outputs.python_jobs }}
requirements: "-r tests/unit/requirements.txt"
# pacboy: "msys/git python-lxml:p"
unittest_report_xml_directory: ${{ needs.ConfigParams.outputs.unittest_report_xml_directory }}
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:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@main
needs:
- ConfigParams
- UnitTestingParams
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
commands: |
${{ needs.ConfigParams.outputs.mypy_prepare_command }}
mypy --html-report report/typing -p ${{ needs.ConfigParams.outputs.package_fullname }}
html_report: 'report/typing'
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
DocCoverage:
uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@main
needs:
- ConfigParams
- UnitTestingParams
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
directory: ${{ inputs.package_namespace }}/${{ inputs.package_name }}
# fail_below: 70
Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@main
needs:
- UnitTestingParams
- UnitTesting
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
# AppTesting:
# uses: pyTooling/Actions/.github/workflows/ApplicationTesting.yml@main
# needs:
# - AppTestingParams
# - UnitTestingParams
# - Package
# with:
# jobs: ${{ needs.AppTestingParams.outputs.python_jobs }}
# wheel: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
# apptest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).apptesting_xml }}
PublishCoverageResults:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@main
needs:
- UnitTestingParams
- UnitTesting
with:
# coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
# coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@main
needs:
- UnitTestingParams
- UnitTesting
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 }}
# VerifyDocs:
# uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@main
# needs:
# - UnitTestingParams
# with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
Documentation:
uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@main
needs:
- ConfigParams
- UnitTestingParams
- PublishTestResults
- PublishCoverageResults
# - VerifyDocs
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
coverage_report_json_directory: ${{ needs.ConfigParams.outputs.coverage_report_json_directory }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-ubuntu-native-3.12
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
IntermediateCleanUp:
uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@main
needs:
- UnitTestingParams
- PublishCoverageResults
- PublishTestResults
- Documentation
with:
sqlite_coverage_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}-
xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-
# PDFDocumentation:
# uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@main
# needs:
# - UnitTestingParams
# - Documentation
# with:
# document: pyEDAA.ProjectModel
# latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
# pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }}
PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@main
needs:
- UnitTestingParams
- Documentation
# - PDFDocumentation
- PublishCoverageResults
- StaticTypeCheck
with:
doc: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
coverage: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
typing: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
ReleasePage:
uses: pyTooling/Actions/.github/workflows/Release.yml@main
if: startsWith(github.ref, 'refs/tags')
needs:
- Package
# - AppTesting
- PublishToGitHubPages
PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@main
if: startsWith(github.ref, 'refs/tags')
needs:
- UnitTestingParams
- ReleasePage
with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
requirements: -r dist/requirements.txt
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@main
needs:
- UnitTestingParams
- UnitTesting
- StaticTypeCheck
- Documentation
# - PDFDocumentation
- PublishTestResults
- PublishCoverageResults
- PublishToGitHubPages
# - PublishOnPyPI
- IntermediateCleanUp
with:
package: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
remaining: |
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}-*
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
# ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).apptesting_xml }}-*
# ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }}

View File

@@ -25,6 +25,11 @@ name: Coverage Collection
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -63,11 +68,17 @@ jobs:
Coverage: Coverage:
name: 📈 Collect Coverage Data using Python ${{ inputs.python_version }} name: 📈 Collect Coverage Data using Python ${{ inputs.python_version }}
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: '❗ Deprecation message'
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
with:
lfs: true
submodules: true
- name: 🐍 Setup Python ${{ inputs.python_version }} - name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -139,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
@@ -152,16 +163,17 @@ jobs:
- name: 📤 Upload 'Coverage Report' artifact - name: 📤 Upload 'Coverage Report' artifact
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.artifact }} name: ${{ inputs.artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_html_directory }} working-directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
path: '*'
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1
- name: 📊 Publish coverage at CodeCov - name: 📊 Publish coverage at CodeCov
continue-on-error: true continue-on-error: true
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v5
with: with:
files: ${{ steps.getVariables.outputs.coverage_report_xml }} files: ${{ steps.getVariables.outputs.coverage_report_xml }}
flags: unittests flags: unittests

View File

@@ -0,0 +1,221 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
name: Extract Configuration
on:
workflow_call:
inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version:
description: 'Python version.'
required: false
default: '3.12'
type: string
package_namespace:
description: 'Name of the tool''s namespace.'
required: false
default: ''
type: string
package_name:
description: 'Name of the tool''s package.'
required: true
type: string
coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false
default: 'pyproject.toml'
type: string
outputs:
package_fullname:
description: ""
value: ${{ jobs.Extract.outputs.package_fullname }}
package_directory:
description: ""
value: ${{ jobs.Extract.outputs.package_directory }}
mypy_prepare_command:
description: ""
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:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_html_directory }}
coverage_report_xml_directory:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml_directory }}
coverage_report_xml_filename:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml_filename }}
coverage_report_xml:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_xml }}
coverage_report_json_directory:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json_directory }}
coverage_report_json_filename:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json_filename }}
coverage_report_json:
description: ""
value: ${{ jobs.Extract.outputs.coverage_report_json }}
jobs:
Extract:
name: 📓 Extract configurations from pyproject.toml
runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
outputs:
package_fullname: ${{ steps.getPackageName.outputs.package_fullname }}
package_directory: ${{ steps.getPackageName.outputs.package_directory }}
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_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_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 }}
steps:
- name: ⏬ Checkout repository
uses: actions/checkout@v4
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
- name: 🔧 Install wheel,tomli and pip dependencies (native)
run: |
python -m pip install --disable-pip-version-check -U wheel tomli
- name: 🔁 Full package name and directory
id: getPackageName
shell: python
run: |
from os import getenv
from pathlib import Path
from textwrap import dedent
namespace = "${{ inputs.package_namespace }}".strip()
name = "${{ inputs.package_name }}".strip()
if namespace == "" or namespace == ".":
fullname = f"{name}"
directory = f"{name}"
mypy_prepare_command = ""
else:
fullname = f"{namespace}.{name}"
directory = f"{namespace}/{name}"
mypy_prepare_command = f"touch {namespace}/__init__.py"
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"""\
package_fullname={fullname}
package_directory={directory}
mypy_prepare_command={mypy_prepare_command}
"""))
- 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
unittestXMLFile = Path("./unittest.xml")
coverageHTMLDirectory = Path("htmlcov")
coverageXMLFile = Path("./coverage.xml")
coverageJSONFile = 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)
unittestXMLFile = Path(pyProjectSettings["tool"]["pytest"]["junit_xml"])
coverageHTMLDirectory = Path(pyProjectSettings["tool"]["coverage"]["html"]["directory"])
coverageXMLFile = Path(pyProjectSettings["tool"]["coverage"]["xml"]["output"])
coverageJSONFile= 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)
coverageHTMLDirectory = Path(coverageRCSettings["html"]["directory"])
coverageXMLFile = Path(coverageRCSettings["xml"]["output"])
coverageJSONFile = 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_xml_directory={unittestXMLFile.parent.as_posix()}
unittest_report_xml_filename={unittestXMLFile.name}
unittest_report_xml={unittestXMLFile.as_posix()}
coverage_report_html_directory={coverageHTMLDirectory.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 unittest xml: {unittestXMLFile}\n coverage html: {coverageHTMLDirectory}\n coverage xml: {coverageXMLFile}\n coverage json: {coverageJSONFile}")

View File

@@ -24,6 +24,11 @@ name: Intermediate Cleanup
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
sqlite_coverage_artifacts_prefix: sqlite_coverage_artifacts_prefix:
description: 'Prefix for SQLite coverage artifacts' description: 'Prefix for SQLite coverage artifacts'
required: false required: false
@@ -36,7 +41,7 @@ on:
jobs: jobs:
IntermediateCleanUp: IntermediateCleanUp:
name: 🗑️ Intermediate Artifact Cleanup name: 🗑️ Intermediate Artifact Cleanup
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: 🗑️ Delete SQLite coverage artifacts from matrix jobs - name: 🗑️ Delete SQLite coverage artifacts from matrix jobs
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v5
@@ -45,7 +50,7 @@ jobs:
with: with:
name: ${{ inputs.sqlite_coverage_artifacts_prefix }}* name: ${{ inputs.sqlite_coverage_artifacts_prefix }}*
- name: 🗑️ Delete XML coverage artifacts from matrix jobs - name: 🗑️ Delete JUnit XML artifacts from matrix jobs
uses: geekyeggo/delete-artifact@v5 uses: geekyeggo/delete-artifact@v5
if: inputs.xml_unittest_artifacts_prefix != '' if: inputs.xml_unittest_artifacts_prefix != ''
continue-on-error: true continue-on-error: true

View File

@@ -24,6 +24,11 @@ name: LaTeX Documentation
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
document: document:
description: 'LaTeX root document without *.tex extension.' description: 'LaTeX root document without *.tex extension.'
required: true required: true
@@ -42,25 +47,36 @@ on:
jobs: jobs:
PDFDocumentation: PDFDocumentation:
name: 📓 Converting LaTeX Documentation to PDF name: 📓 Converting LaTeX Documentation to PDF
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: 📥 Download artifacts '${{ inputs.latex_artifact }}' from 'SphinxDocumentation' job - name: 📥 Download artifacts '${{ inputs.latex_artifact }}' from 'SphinxDocumentation' job
uses: actions/download-artifact@v4 uses: pyTooling/download-artifact@v4
with: with:
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: actions/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

530
.github/workflows/NightlyRelease.yml vendored Normal file
View File

@@ -0,0 +1,530 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
name: Nightly
on:
workflow_call:
inputs:
ubuntu_image:
description: 'Name of the Ubuntu image.'
required: false
default: 'ubuntu-24.04'
type: string
nightly_name:
description: 'Name of the nightly release.'
required: false
default: 'nightly'
type: string
nightly_title:
description: 'Title of the nightly release.'
required: false
default: ''
type: string
nightly_description:
description: 'Description of the nightly release.'
required: false
default: 'Release of artifacts from latest CI pipeline.'
type: string
draft:
description: 'Specify if this is a draft.'
required: false
default: false
type: boolean
prerelease:
description: 'Specify if this is a pre-release.'
required: false
default: false
type: boolean
latest:
description: 'Specify if this is the latest release.'
required: false
default: false
type: boolean
replacements:
description: 'Multi-line string containing search=replace patterns.'
required: false
default: ''
type: string
assets:
description: 'Multi-line string containing artifact:file:title asset descriptions.'
required: true
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:
type: string
required: false
default: '__pyTooling_upload_artifact__.tar'
can-fail:
type: boolean
required: false
default: false
jobs:
Release:
name: 📝 Update 'Nightly Page' on GitHub
runs-on: ${{ inputs.ubuntu_image }}
continue-on-error: ${{ inputs.can-fail }}
permissions:
contents: write
actions: write
# attestations: write
steps:
- name: ⏬ Checkout repository
uses: actions/checkout@v4
with:
# The command 'git describe' (used for version) needs the history.
fetch-depth: 0
- name: 🔧 Install zstd
run: sudo apt-get install -y --no-install-recommends zstd
- name: 📑 Delete (old) Release Page
id: deleteReleasePage
run: |
set +e
ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_LIGHT_YELLOW=$'\x1b[93m'
ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }}
printf "%s" "Deleting release '${{ inputs.nightly_name }}' ... "
message="$(gh release delete ${{ inputs.nightly_name }} --yes 2>&1)"
if [[ $? -eq 0 ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
elif [[ "${message}" == "release not found" ]]; then
printf "%s\n" "${ANSI_LIGHT_YELLOW}[NOT FOUND]${ANSI_NOCOLOR}"
else
printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
printf " %s\n" "${ANSI_LIGHT_RED}Couldn't delete release '${{ inputs.nightly_name }}' -> Error: '${message}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=InternalError::Couldn't delete release '${{ inputs.nightly_name }}' -> Error: '${message}'."
exit 1
fi
- name: 📑 (Re)create (new) Release Page
id: createReleasePage
run: |
set +e
ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }}
addDraft="--draft"
if [[ "${{ inputs.prerelease }}" == "true" ]]; then
addPreRelease="--prerelease"
fi
if [[ "${{ inputs.latest }}" == "false" ]]; then
addLatest="--latest=false"
fi
if [[ "${{ inputs.nightly_title }}" != "" ]]; then
addTitle=("--title" "${{ inputs.nightly_title }}")
fi
cat <<'EOF' > __NoTeS__.md
${{ inputs.nightly_description }}
EOF
if [[ -s __NoTeS__.md ]]; then
addNotes=("--notes-file" "__NoTeS__.md")
fi
# Apply replacements
while IFS=$'\r\n' read -r patternLine; do
# skip empty lines
[[ "$patternLine" == "" ]] && continue
pattern="${patternLine%%=*}"
replacement="${patternLine#*=}"
sed -i -e "s/%$pattern%/$replacement/g" "__NoTeS__.md"
done <<<'${{ inputs.replacements }}'
# Add footer line
cat <<EOF >> __NoTeS__.md
--------
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 %Z').
EOF
printf "%s\n" "Creating release '${{ inputs.nightly_name }}' ... "
message="$(gh release create "${{ inputs.nightly_name }}" --verify-tag $addDraft $addPreRelease $addLatest "${addTitle[@]}" "${addNotes[@]}" 2>&1)"
if [[ $? -eq 0 ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
else
printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
printf " %s\n" "${ANSI_LIGHT_RED}Couldn't create release '${{ inputs.nightly_name }}' -> Error: '${message}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=InternalError::Couldn't create release '${{ inputs.nightly_name }}' -> Error: '${message}'."
exit 1
fi
- name: 📥 Download artifacts and upload as assets
id: uploadAssets
run: |
set +e
ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_LIGHT_YELLOW=$'\x1b[93m'
ANSI_LIGHT_BLUE=$'\x1b[94m'
ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }}
Replace() {
line="$1"
while IFS=$'\r\n' read -r patternLine; do
# skip empty lines
[[ "$patternLine" == "" ]] && continue
pattern="${patternLine%%=*}"
replacement="${patternLine#*=}"
line="${line//"%$pattern%"/"$replacement"}"
done <<<'${{ inputs.replacements }}'
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
# A dictionary of 0/1 to avoid duplicate downloads
declare -A downloadedArtifacts
# A dictionary to check for duplicate asset files in release
declare -A assetFilenames
while IFS=$'\r\n' read -r assetLine; do
if [[ "${assetLine}" == "" || "${assetLine:0:1}" == "#" ]]; then
continue
fi
# split assetLine colon separated triple: artifact:asset:title
artifact="${assetLine%%:*}"
assetLine="${assetLine#*:}"
asset="${assetLine%%:*}"
assetLine="${assetLine#*:}"
if [[ "${{ inputs.inventory-json }}" == "" ]]; then
categories=""
title="${assetLine##*:}"
else
categories="${assetLine%%:*}"
title="${assetLine##*:}"
fi
# remove leading whitespace
asset="${asset#"${asset%%[![:space:]]*}"}"
categories="${categories#"${categories%%[![:space:]]*}"}"
title="${title#"${title%%[![:space:]]*}"}"
# apply replacements
asset="$(Replace "${asset}")"
title="$(Replace "${title}")"
printf "%s\n" "Publish asset '${asset}' from artifact '${artifact}' with title '${title}'"
printf " %s" "Checked asset for duplicates ... "
if [[ -n "${assetFilenames[$asset]}" ]]; then
printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
printf "%s\n" "::error title=DuplicateAsset::Asset '${asset}' from artifact '${artifact}' was already uploaded to release '${{ inputs.nightly_name }}'."
ERRORS=$((ERRORS + 1))
continue
else
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
assetFilenames[$asset]=1
fi
# Download artifact by artifact name
if [[ -n "${downloadedArtifacts[$artifact]}" ]]; then
printf " %s\n" "downloading '${artifact}' ... ${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}"
else
echo " downloading '${artifact}' ... "
printf " %s" "gh run download $GITHUB_RUN_ID --dir \"${artifact}\" --name \"${artifact}\" "
gh run download $GITHUB_RUN_ID --dir "${artifact}" --name "${artifact}"
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 download artifact '${artifact}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=ArtifactNotFound::Couldn't download artifact '${artifact}'."
ERRORS=$((ERRORS + 1))
continue
fi
downloadedArtifacts[$artifact]=1
printf " %s" "Checking for embedded tarball ... "
if [[ -f "${artifact}/${{ inputs.tarball-name }}" ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[FOUND]${ANSI_NOCOLOR}"
pushd "${artifact}" > /dev/null
printf " %s" "Extracting embedded tarball ... "
tar -xf "${{ inputs.tarball-name }}"
if [[ $? -ne 0 ]]; then
printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
else
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
fi
printf " %s" "Removing temporary tarball ... "
rm -f "${{ inputs.tarball-name }}"
if [[ $? -ne 0 ]]; then
printf "%s\n" "${ANSI_LIGHT_RED}[FAILED]${ANSI_NOCOLOR}"
else
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
fi
popd > /dev/null
else
printf "%s\n" "${ANSI_LIGHT_YELLOW}[SKIPPED]${ANSI_NOCOLOR}"
fi
fi
# Check if artifact should be compressed (zip, tgz) or if asset was part of the downloaded artifact.
printf " %s" "checking asset '${artifact}/${asset}' ... "
if [[ "${asset}" == !*.zip ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[ZIP]${ANSI_NOCOLOR}"
asset="${asset##*!}"
printf "::group:: %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
(
cd "${artifact}" && \
zip -r "../${asset}" *
)
retCode=$?
printf "::endgroup::\n"
if [[ $retCode -eq 0 ]]; then
printf " %s\n" "Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${asset}"
else
printf " %s\n" "Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
printf " %s\n" "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to zip file '${asset}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=CompressionError::Couldn't compress '${artifact}' to zip file '${asset}'."
ERRORS=$((ERRORS + 1))
continue
fi
elif [[ "${asset}" == !*.tgz || "${asset}" == !*.tar.gz || "${asset}" == \$*.tgz || "${asset}" == \$*.tar.gz ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[TAR/GZ]${ANSI_NOCOLOR}"
if [[ "${asset:0:1}" == "\$" ]]; then
asset="${asset##*$}"
dirName="${asset%.*}"
printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
tar -c --gzip --owner=0 --group=0 --file="${asset}" --directory="${artifact}" --transform "s|^\.|${dirName%.tar}|" .
retCode=$?
else
asset="${asset##*!}"
printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
(
cd "${artifact}" && \
tar -c --gzip --owner=0 --group=0 --file="../${asset}" *
)
retCode=$?
fi
if [[ $retCode -eq 0 ]]; then
printf " %s\n" "Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${asset}"
else
printf " %s\n" "Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
printf " %s\n" "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to tgz file '${asset}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=CompressionError::Couldn't compress '${artifact}' to tgz file '${asset}'."
ERRORS=$((ERRORS + 1))
continue
fi
elif [[ "${asset}" == !*.tzst || "${asset}" == !*.tar.zst || "${asset}" == \$*.tzst || "${asset}" == \$*.tar.zst ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[ZST]${ANSI_NOCOLOR}"
if [[ "${asset:0:1}" == "\$" ]]; then
asset="${asset##*$}"
dirName="${asset%.*}"
printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
tar -c --zstd --owner=0 --group=0 --file="${asset}" --directory="${artifact}" --transform "s|^\.|${dirName%.tar}|" .
retCode=$?
else
asset="${asset##*!}"
printf " %s\n" "Compressing artifact '${artifact}' to '${asset}' ..."
(
cd "${artifact}" && \
tar -c --zstd --owner=0 --group=0 --file="../${asset}" *
)
retCode=$?
fi
if [[ $retCode -eq 0 ]]; then
printf " %s\n" "Compression ${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${asset}"
else
printf " %s\n" "Compression ${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
printf " %s\n" "${ANSI_LIGHT_RED}Couldn't compress '${artifact}' to zst file '${asset}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=CompressionError::Couldn't compress '${artifact}' to zst file '${asset}'."
ERRORS=$((ERRORS + 1))
continue
fi
elif [[ -e "${artifact}/${asset}" ]]; then
printf "%s\n" "${ANSI_LIGHT_GREEN}[OK]${ANSI_NOCOLOR}"
uploadFile="${artifact}/${asset}"
else
printf "%s\n" "${ANSI_LIGHT_RED}[ERROR]${ANSI_NOCOLOR}"
printf " %s\n" "${ANSI_LIGHT_RED}Couldn't find asset '${asset}' in artifact '${artifact}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=FileNotFound::Couldn't find asset '${asset}' in artifact '${artifact}'."
ERRORS=$((ERRORS + 1))
continue
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
printf " %s" "uploading asset '${asset}' from '${uploadFile}' with title '${title}' ... "
gh release upload ${{ inputs.nightly_name }} "${uploadFile}#${title}" --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 '${asset}' from '${uploadFile}' to release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=UploadError::Couldn't upload asset '${asset}' from '${uploadFile}' to release '${{ inputs.nightly_name }}'."
ERRORS=$((ERRORS + 1))
continue
fi
done <<<'${{ inputs.assets }}'
if [[ "${{ inputs.inventory-json }}" != "" ]]; then
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=$((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 [[ $ERRORS -ne 0 ]]; then
printf "%s\n" "${ANSI_LIGHT_RED}${ERRORS} errors detected in previous steps.${ANSI_NOCOLOR}"
exit 1
fi
- name: 📑 Remove draft state from Release Page
if: ${{ ! inputs.draft }}
run: |
set +e
ANSI_LIGHT_RED=$'\x1b[91m'
ANSI_LIGHT_GREEN=$'\x1b[92m'
ANSI_NOCOLOR=$'\x1b[0m'
export GH_TOKEN=${{ github.token }}
# Remove draft-state from release page
printf "%s" "Remove draft-state from release '${title}' ... "
gh release edit --draft=false "${{ inputs.nightly_name }}"
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 remove draft-state from release '${{ inputs.nightly_name }}'.${ANSI_NOCOLOR}"
printf "%s\n" "::error title=ReleasePage::Couldn't remove draft-state from release '${{ inputs.nightly_name }}'."
fi

View File

@@ -25,6 +25,11 @@ name: Package
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -44,11 +49,14 @@ jobs:
Package: Package:
name: 📦 Package in Source and Wheel Format name: 📦 Package in Source and Wheel Format
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
lfs: true
submodules: true
- name: 🐍 Setup Python ${{ inputs.python_version }} - name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v5 uses: actions/setup-python@v5
@@ -98,9 +106,10 @@ jobs:
run: python setup.py bdist_wheel run: python setup.py bdist_wheel
- name: 📤 Upload wheel artifact - name: 📤 Upload wheel artifact
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.artifact }} name: ${{ inputs.artifact }}
path: dist/ working-directory: dist
path: '*'
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -25,24 +25,40 @@ name: Parameters
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
name: name:
description: 'Name of the tool.' description: 'Name of the tool.'
required: true required: false
default: ''
type: string
package_namespace:
description: 'Name of the tool''s namespace.'
required: false
default: ''
type: string
package_name:
description: 'Name of the tool''s package.'
required: false
default: ''
type: string type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
default: '3.12' default: '3.13'
type: string type: string
python_version_list: python_version_list:
description: 'Space separated list of Python versions to run tests with.' description: 'Space separated list of Python versions to run tests with.'
required: false required: false
default: '3.8 3.9 3.10 3.11 3.12' default: '3.9 3.10 3.11 3.12 3.13'
type: string type: string
system_list: system_list:
description: 'Space separated list of systems to run tests on.' description: 'Space separated list of systems to run tests on.'
required: false required: false
default: 'ubuntu windows macos-arm mingw64 ucrt64' default: 'ubuntu windows macos macos-arm mingw64 ucrt64'
type: string type: string
include_list: include_list:
description: 'Space separated list of system:python items to be included into the list of test.' description: 'Space separated list of system:python items to be included into the list of test.'
@@ -67,17 +83,17 @@ on:
windows_image: windows_image:
description: 'The used GitHub Action image for Windows based jobs.' description: 'The used GitHub Action image for Windows based jobs.'
required: false required: false
default: 'windows-latest' default: 'windows-2022'
type: string type: string
macos_intel_image: macos_intel_image:
description: 'The used GitHub Action image for macOS (Intel x86-64) based jobs.' description: 'The used GitHub Action image for macOS (Intel x86-64) based jobs.'
required: false required: false
default: 'macos-latest-large' default: 'macos-13'
type: string type: string
macos_arm_image: macos_arm_image:
description: 'The used GitHub Action image for macOS (ARM arm64) based jobs.' description: 'The used GitHub Action image for macOS (ARM aarch64) based jobs.'
required: false required: false
default: 'macos-latest' default: 'macos-14'
type: string type: string
outputs: outputs:
@@ -96,7 +112,8 @@ on:
jobs: jobs:
Parameters: Parameters:
runs-on: ubuntu-24.04 name: ✎ Generate pipeline parameters
runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
outputs: outputs:
python_version: ${{ steps.params.outputs.python_version }} python_version: ${{ steps.params.outputs.python_version }}
python_jobs: ${{ steps.params.outputs.python_jobs }} python_jobs: ${{ steps.params.outputs.python_jobs }}
@@ -114,7 +131,9 @@ jobs:
from textwrap import dedent from textwrap import dedent
from typing import Iterable from typing import Iterable
name = "${{ inputs.name }}".strip() package_namespace = "${{ inputs.package_namespace }}".strip()
package_name = "${{ inputs.package_name }}".strip()
name = "${{ inputs.name }}".strip()
python_version = "${{ inputs.python_version }}".strip() python_version = "${{ inputs.python_version }}".strip()
systems = "${{ inputs.system_list }}".strip() systems = "${{ inputs.system_list }}".strip()
versions = "${{ inputs.python_version_list }}".strip() versions = "${{ inputs.python_version_list }}".strip()
@@ -122,9 +141,15 @@ jobs:
exclude_list = "${{ inputs.exclude_list }}".strip() exclude_list = "${{ inputs.exclude_list }}".strip()
disable_list = "${{ inputs.disable_list }}".strip() disable_list = "${{ inputs.disable_list }}".strip()
currentMSYS2Version = "3.11" if name == "":
currentAlphaVersion = "3.13" if package_namespace == "" or package_namespace == ".":
currentAlphaRelease = "3.13.0-alpha.1" name = f"{package_name}"
else:
name = f"{package_namespace}.{package_name}"
currentMSYS2Version = "3.12"
currentAlphaVersion = "3.14"
currentAlphaRelease = "3.14.0-alpha.1"
if systems == "": if systems == "":
print("::error title=Parameter::system_list is empty.") print("::error title=Parameter::system_list is empty.")
@@ -151,8 +176,8 @@ jobs:
else: else:
disabled = [disable.strip() for disable in disable_list.split(" ")] disabled = [disable.strip() for disable in disable_list.split(" ")]
if "3.7" in versions: if "3.8" in versions:
print("::warning title=Deprecated::Support for Python 3.7 ended in 2023.06.27.") print("::warning title=Deprecated::Support for Python 3.8 ended in 2024.10.")
if "msys2" in systems: if "msys2" in systems:
print("::warning title=Deprecated::System 'msys2' will be replaced by 'mingw64'.") print("::warning title=Deprecated::System 'msys2' will be replaced by 'mingw64'.")
if currentAlphaVersion in versions: if currentAlphaVersion in versions:
@@ -164,24 +189,25 @@ jobs:
data = { data = {
# Python and PyPy versions supported by "setup-python" action # Python and PyPy versions supported by "setup-python" action
"python": { "python": {
"3.7": { "icon": "⚫", "until": "2023.06.27" }, "3.8": { "icon": "⚫", "until": "2024.10" },
"3.8": { "icon": "🔴", "until": "2024.10" }, "3.9": { "icon": "🔴", "until": "2025.10" },
"3.9": { "icon": "🟠", "until": "2025.10" }, "3.10": { "icon": "🟠", "until": "2026.10" },
"3.10": { "icon": "🟡", "until": "2026.10" }, "3.11": { "icon": "🟡", "until": "2027.10" },
"3.11": { "icon": "🟢", "until": "2027.10" },
"3.12": { "icon": "🟢", "until": "2028.10" }, "3.12": { "icon": "🟢", "until": "2028.10" },
# "3.13": { "icon": "🟣", "until": "2028.10" }, "3.13": { "icon": "🟢", "until": "2029.10" },
"3.14": { "icon": "🟣", "until": "2030.10" },
"pypy-3.7": { "icon": "⟲⚫", "until": "????.??" }, "pypy-3.7": { "icon": "⟲⚫", "until": "????.??" },
"pypy-3.8": { "icon": "⟲🔴", "until": "????.??" }, "pypy-3.8": { "icon": "⟲", "until": "????.??" },
"pypy-3.9": { "icon": "⟲🟠", "until": "????.??" }, "pypy-3.9": { "icon": "⟲🔴", "until": "????.??" },
"pypy-3.10": { "icon": "⟲🟡", "until": "????.??" }, "pypy-3.10": { "icon": "⟲🟠", "until": "????.??" },
"pypy-3.11": { "icon": "⟲🟡", "until": "????.??" },
}, },
# Runner systems (runner images) supported by GitHub Actions # Runner systems (runner images) supported by GitHub Actions
"sys": { "sys": {
"ubuntu": { "icon": "🐧", "runs-on": "${{ inputs.ubuntu_image }}", "shell": "bash", "name": "Linux (x86-64)" }, "ubuntu": { "icon": "🐧", "runs-on": "${{ inputs.ubuntu_image }}", "shell": "bash", "name": "Linux (x86-64)" },
"windows": { "icon": "🪟", "runs-on": "${{ inputs.windows_image }}", "shell": "pwsh", "name": "Windows (x86-64)" }, "windows": { "icon": "🪟", "runs-on": "${{ inputs.windows_image }}", "shell": "pwsh", "name": "Windows (x86-64)" },
"macos": { "icon": "🍎", "runs-on": "${{ inputs.macos_intel_image }}", "shell": "bash", "name": "macOS (x86-64)" }, "macos": { "icon": "🍎", "runs-on": "${{ inputs.macos_intel_image }}", "shell": "bash", "name": "macOS (x86-64)" },
"macos-arm": { "icon": "🍏", "runs-on": "${{ inputs.macos_arm_image }}", "shell": "bash", "name": "macOS (arm64)" }, "macos-arm": { "icon": "🍏", "runs-on": "${{ inputs.macos_arm_image }}", "shell": "bash", "name": "macOS (aarch64)" },
}, },
# Runtimes provided by MSYS2 # Runtimes provided by MSYS2
"runtime": { "runtime": {
@@ -290,18 +316,6 @@ jobs:
"documentation_pdf": f"{name}-Documentation-PDF", "documentation_pdf": f"{name}-Documentation-PDF",
} }
# Deprecated structure
params = {
"python_version": python_version,
"artifacts": {
"unittesting": f"{artifact_names['unittesting_xml']}",
"coverage": f"{artifact_names['codecoverage_html']}",
"typing": f"{artifact_names['statictyping_html']}",
"package": f"{artifact_names['package_all']}",
"doc": f"{artifact_names['documentation_html']}",
}
}
print("Parameters:") print("Parameters:")
print(f" python_version: {python_version}") print(f" python_version: {python_version}")
print(f" python_jobs ({len(jobs)}):\n" + print(f" python_jobs ({len(jobs)}):\n" +
@@ -319,13 +333,12 @@ jobs:
python_version={python_version} python_version={python_version}
python_jobs={json_dumps(jobs)} python_jobs={json_dumps(jobs)}
artifact_names={json_dumps(artifact_names)} artifact_names={json_dumps(artifact_names)}
params={json_dumps(params)}
""")) """))
- 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

@@ -24,6 +24,15 @@ name: Publish Code Coverage Results
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
coverage_artifacts_pattern:
required: false
default: '*-CodeCoverage-SQLite-*'
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
@@ -57,18 +66,26 @@ on:
jobs: jobs:
PublishCoverageResults: PublishCoverageResults:
name: 📊 Publish Code Coverage Results name: 📊 Publish Code Coverage Results
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
if: always() if: always()
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Download Artifacts
uses: actions/download-artifact@v4
with: with:
lfs: true
submodules: true
- name: 📥 Download Artifacts
uses: pyTooling/download-artifact@v4
with:
pattern: ${{ inputs.coverage_artifacts_pattern }}
path: artifacts path: artifacts
- name: 🔎 Inspect extracted artifact (tarball)
run: |
tree -pash artifacts
- name: 🔧 Install coverage and tomli - name: 🔧 Install coverage and tomli
run: | run: |
python -m pip install -U --disable-pip-version-check --break-system-packages coverage[toml] tomli python -m pip install -U --disable-pip-version-check --break-system-packages coverage[toml] tomli
@@ -133,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/
@@ -160,12 +175,12 @@ 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
uses: pyTooling/upload-artifact@v4
if: inputs.coverage_sqlite_artifact != '' if: inputs.coverage_sqlite_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_sqlite_artifact }} name: ${{ inputs.coverage_sqlite_artifact }}
path: .coverage path: .coverage
@@ -173,9 +188,9 @@ jobs:
retention-days: 1 retention-days: 1
- name: 📤 Upload 'Coverage XML Report' artifact - name: 📤 Upload 'Coverage XML Report' artifact
uses: pyTooling/upload-artifact@v4
if: inputs.coverage_xml_artifact != '' if: inputs.coverage_xml_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_xml_artifact }} name: ${{ inputs.coverage_xml_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_xml }} path: ${{ steps.getVariables.outputs.coverage_report_xml }}
@@ -183,9 +198,9 @@ jobs:
retention-days: 1 retention-days: 1
- name: 📤 Upload 'Coverage JSON Report' artifact - name: 📤 Upload 'Coverage JSON Report' artifact
uses: pyTooling/upload-artifact@v4
if: inputs.coverage_json_artifact != '' if: inputs.coverage_json_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_json_artifact }} name: ${{ inputs.coverage_json_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_json }} path: ${{ steps.getVariables.outputs.coverage_report_json }}
@@ -193,28 +208,29 @@ jobs:
retention-days: 1 retention-days: 1
- name: 📤 Upload 'Coverage HTML Report' artifact - name: 📤 Upload 'Coverage HTML Report' artifact
uses: pyTooling/upload-artifact@v4
if: inputs.coverage_html_artifact != '' if: inputs.coverage_html_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_html_artifact }} name: ${{ inputs.coverage_html_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_html_directory }} working-directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
path: '*'
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1
- name: 📊 Publish code coverage at CodeCov - name: 📊 Publish code coverage at CodeCov
uses: codecov/codecov-action@v5
if: inputs.CodeCov == true if: inputs.CodeCov == true
continue-on-error: true continue-on-error: true
uses: codecov/codecov-action@v4
with: with:
files: ${{ steps.getVariables.outputs.coverage_report_xml }} files: ${{ steps.getVariables.outputs.coverage_report_xml }}
flags: unittests flags: unittests
env_vars: PYTHON env_vars: PYTHON
- name: 📉 Publish code coverage at Codacy - name: 📉 Publish code coverage at Codacy
uses: codacy/codacy-coverage-reporter-action@v1
if: inputs.Codacy == true if: inputs.Codacy == true
continue-on-error: true continue-on-error: true
uses: codacy/codacy-coverage-reporter-action@v1
with: with:
project-token: ${{ secrets.codacy_token }} project-token: ${{ secrets.codacy_token }}
coverage-reports: ${{ steps.getVariables.outputs.coverage_report_xml }} coverage-reports: ${{ steps.getVariables.outputs.coverage_report_xml }}

View File

@@ -25,6 +25,11 @@ name: Publish on PyPI
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -48,14 +53,14 @@ jobs:
PublishOnPyPI: PublishOnPyPI:
name: 🚀 Publish to PyPI name: 🚀 Publish to PyPI
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: 📥 Download artifacts '${{ inputs.artifact }}' from 'Package' job - name: 📥 Download artifacts '${{ inputs.artifact }}' from 'Package' job
uses: actions/download-artifact@v4 uses: pyTooling/download-artifact@v4
with: with:
name: ${{ inputs.artifact }} name: ${{ inputs.artifact }}
path: dist/ path: dist
- name: 🐍 Setup Python ${{ inputs.python_version }} - name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v5 uses: actions/setup-python@v5

View File

@@ -25,6 +25,15 @@ name: Publish Unit Test Results
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
unittest_artifacts_pattern:
required: false
default: '*-UnitTestReportSummary-XML-*'
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.'
required: false required: false
@@ -35,6 +44,11 @@ on:
required: false required: false
default: '"--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit"' default: '"--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit"'
type: string type: string
publish:
description: 'Publish test report summary via Dorny Test-Reporter'
required: false
default: true
type: boolean
report_title: report_title:
description: 'Title of the summary report in the pipeline''s sidebar' description: 'Title of the summary report in the pipeline''s sidebar'
required: false required: false
@@ -44,45 +58,50 @@ on:
jobs: jobs:
PublishTestResults: PublishTestResults:
name: 📊 Publish Test Results name: 📊 Publish Test Results
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
if: always() if: always()
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Download Artifacts - name: 📥 Download Artifacts
uses: actions/download-artifact@v4 uses: pyTooling/download-artifact@v4
with: with:
pattern: ${{ inputs.unittest_artifacts_pattern }}
path: artifacts path: artifacts
- name: 🔎 Inspect extracted artifact (tarball)
run: |
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 "*.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 -pash junit
tree -a 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=ant-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
uses: dorny/test-reporter@v1 uses: dorny/test-reporter@v1
if: inputs.publish && inputs.report_title != ''
with: with:
name: ${{ inputs.report_title }} name: ${{ inputs.report_title }}
path: Unittesting.xml path: Unittesting.xml
reporter: java-junit reporter: java-junit
- name: 📤 Upload merged 'JUnit Test Summary' artifact - name: 📤 Upload merged 'JUnit Test Summary' artifact
uses: pyTooling/upload-artifact@v4
if: inputs.merged_junit_artifact != '' if: inputs.merged_junit_artifact != ''
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.merged_junit_artifact }} name: ${{ inputs.merged_junit_artifact }}
path: Unittesting.xml path: Unittesting.xml

View File

@@ -25,6 +25,11 @@ name: Publish to GitHub Pages
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
doc: doc:
description: 'Name of the documentation artifact.' description: 'Name of the documentation artifact.'
required: true required: true
@@ -44,28 +49,28 @@ jobs:
PublishToGitHubPages: PublishToGitHubPages:
name: 📚 Publish to GH-Pages name: 📚 Publish to GH-Pages
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- 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: actions/download-artifact@v4 uses: pyTooling/download-artifact@v4
with: with:
name: ${{ inputs.doc }} name: ${{ inputs.doc }}
path: public path: public
- name: 📥 Download artifacts '${{ inputs.coverage }}' from 'Coverage' job - name: 📥 Download artifacts '${{ inputs.coverage }}' from 'Coverage' job
uses: pyTooling/download-artifact@v4
if: ${{ inputs.coverage != '' }} if: ${{ inputs.coverage != '' }}
uses: actions/download-artifact@v4
with: with:
name: ${{ inputs.coverage }} name: ${{ inputs.coverage }}
path: public/coverage path: public/coverage
- name: 📥 Download artifacts '${{ inputs.typing }}' from 'StaticTypeCheck' job - name: 📥 Download artifacts '${{ inputs.typing }}' from 'StaticTypeCheck' job
uses: pyTooling/download-artifact@v4
if: ${{ inputs.typing != '' }} if: ${{ inputs.typing != '' }}
uses: actions/download-artifact@v4
with: with:
name: ${{ inputs.typing }} name: ${{ inputs.typing }}
path: public/typing path: public/typing

View File

@@ -24,12 +24,17 @@ name: Release
on: on:
workflow_call: workflow_call:
inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
jobs: jobs:
Release: Release:
name: 📝 Create 'Release Page' on GitHub name: 📝 Create 'Release Page' on GitHub
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: 🔁 Extract Git tag from GITHUB_REF - name: 🔁 Extract Git tag from GITHUB_REF
@@ -44,8 +49,8 @@ jobs:
echo "datetime=${RELEASE_DATETIME}" >> $GITHUB_OUTPUT echo "datetime=${RELEASE_DATETIME}" >> $GITHUB_OUTPUT
- name: 📑 Create Release Page - name: 📑 Create Release Page
id: createReleasePage
uses: actions/create-release@v1 uses: actions/create-release@v1
id: createReleasePage
env: env:
GITHUB_TOKEN: ${{ github.token }} GITHUB_TOKEN: ${{ github.token }}
with: with:

View File

@@ -24,6 +24,11 @@ name: Documentation
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -34,16 +39,15 @@ on:
required: false required: false
default: '-r doc/requirements.txt' default: '-r doc/requirements.txt'
type: string type: string
coverage_config:
description: 'Path to the .coveragerc file. Use pyproject.toml by default.'
required: false
default: 'pyproject.toml'
type: string
doc_directory: doc_directory:
description: 'Path to the directory containing documentation (Sphinx working directory).' description: 'Path to the directory containing documentation (Sphinx working directory).'
required: false required: false
default: 'doc' default: 'doc'
type: string type: string
coverage_report_json_directory:
description: ''
required: false
type: string
coverage_json_artifact: coverage_json_artifact:
description: 'Name of the coverage JSON artifact.' description: 'Name of the coverage JSON artifact.'
required: false required: false
@@ -71,13 +75,16 @@ on:
type: string type: string
jobs: jobs:
Sphinx: Sphinx-HTML:
name: 📓 Documentation generation using Sphinx and Python ${{ inputs.python_version }} name: 📓 HTML Documentation using Sphinx and Python ${{ inputs.python_version }}
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
lfs: true
submodules: true
- name: 🔧 Install graphviz - name: 🔧 Install graphviz
run: sudo apt-get install -y --no-install-recommends graphviz run: sudo apt-get install -y --no-install-recommends graphviz
@@ -89,84 +96,22 @@ 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 wheel tomli python -m pip install --disable-pip-version-check -U wheel
python -m pip install --disable-pip-version-check ${{ inputs.requirements }} python -m pip install --disable-pip-version-check ${{ inputs.requirements }}
- 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"""\
coverage_report_html_directory={htmlDirectory.as_posix()}
coverage_report_xml_directory={xmlFile.parent.as_posix()}
coverage_report_xml={xmlFile.as_posix()}
coverage_report_json_directory={jsonFile.parent.as_posix()}
coverage_report_json={jsonFile.as_posix()}
"""))
print(f"DEBUG:\n html={htmlDirectory}\n xml={xmlFile}\n json={jsonFile}")
- name: 📥 Download artifacts '${{ inputs.unittest_xml_artifact }}' from 'Unittesting' job - name: 📥 Download artifacts '${{ inputs.unittest_xml_artifact }}' from 'Unittesting' job
uses: pyTooling/download-artifact@v4
if: inputs.unittest_xml_artifact != '' if: inputs.unittest_xml_artifact != ''
uses: actions/download-artifact@v4
with: with:
name: ${{ inputs.unittest_xml_artifact }} name: ${{ inputs.unittest_xml_artifact }}
path: ${{ inputs.unittest_xml_directory }} path: ${{ inputs.unittest_xml_directory }}
- name: 📥 Download artifacts '${{ inputs.coverage_json_artifact }}' from 'PublishCoverageResults' job - name: 📥 Download artifacts '${{ inputs.coverage_json_artifact }}' from 'PublishCoverageResults' job
uses: pyTooling/download-artifact@v4
if: inputs.coverage_json_artifact != '' if: inputs.coverage_json_artifact != ''
uses: actions/download-artifact@v4
with: with:
name: ${{ inputs.coverage_json_artifact }} name: ${{ inputs.coverage_json_artifact }}
path: ${{ steps.getVariables.outputs.coverage_report_json_directory }} path: ${{ inputs.coverage_report_json_directory }}
- name: ☑ Generate HTML documentation - name: ☑ Generate HTML documentation
if: inputs.html_artifact != '' if: inputs.html_artifact != ''
@@ -176,6 +121,55 @@ jobs:
cd "${{ inputs.doc_directory || '.' }}" cd "${{ inputs.doc_directory || '.' }}"
sphinx-build -v -n -b html -d _build/doctrees -j $(nproc) -w _build/html.log . _build/html sphinx-build -v -n -b html -d _build/doctrees -j $(nproc) -w _build/html.log . _build/html
- name: 📤 Upload 'HTML Documentation' artifact
uses: pyTooling/upload-artifact@v4
if: inputs.html_artifact != ''
continue-on-error: true
with:
name: ${{ inputs.html_artifact }}
working-directory: ${{ inputs.doc_directory }}/_build/html
path: '*'
if-no-files-found: error
retention-days: 1
Sphinx-LaTeX:
name: 📓 LaTeX Documentation using Sphinx and Python ${{ inputs.python_version }}
runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps:
- name: ⏬ Checkout repository
uses: actions/checkout@v4
with:
lfs: true
submodules: true
- name: 🔧 Install graphviz
run: sudo apt-get install -y --no-install-recommends graphviz
- name: 🐍 Setup Python ${{ inputs.python_version }}
uses: actions/setup-python@v5
with:
python-version: ${{ inputs.python_version }}
- name: 🔧 Install wheel,tomli and pip dependencies (native)
run: |
python -m pip install --disable-pip-version-check -U wheel
python -m pip install --disable-pip-version-check ${{ inputs.requirements }}
- name: 📥 Download artifacts '${{ inputs.unittest_xml_artifact }}' from 'Unittesting' job
uses: pyTooling/download-artifact@v4
if: inputs.unittest_xml_artifact != ''
with:
name: ${{ inputs.unittest_xml_artifact }}
path: ${{ inputs.unittest_xml_directory }}
- name: 📥 Download artifacts '${{ inputs.coverage_json_artifact }}' from 'PublishCoverageResults' job
uses: pyTooling/download-artifact@v4
if: inputs.coverage_json_artifact != ''
with:
name: ${{ inputs.coverage_json_artifact }}
path: ${{ inputs.coverage_report_json_directory }}
- name: ☑ Generate LaTeX documentation - name: ☑ Generate LaTeX documentation
if: inputs.latex_artifact != '' if: inputs.latex_artifact != ''
# continue-on-error: true # continue-on-error: true
@@ -186,22 +180,95 @@ 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: 📤 Upload 'HTML Documentation' artifact - name: Workaround I - https://github.com/sphinx-doc/sphinx/issues/13190
if: inputs.html_artifact != '' if: inputs.latex_artifact != ''
continue-on-error: true run: |
uses: actions/upload-artifact@v4 printf "Changing directory to '${{ inputs.doc_directory || '.' }}/_build/latex' ...\n"
with: cd ${{ inputs.doc_directory || '.' }}/_build/latex
name: ${{ inputs.html_artifact }}
path: ${{ inputs.doc_directory }}/_build/html MIMETYPE_EXTENSIONS=(
if-no-files-found: error "image/png:png"
retention-days: 1 "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 '${{ inputs.doc_directory || '.' }}/_build/latex' ...\n"
cd ${{ inputs.doc_directory || '.' }}/_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
uses: pyTooling/upload-artifact@v4
if: inputs.latex_artifact != '' if: inputs.latex_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.latex_artifact }} name: ${{ inputs.latex_artifact }}
path: ${{ inputs.doc_directory }}/_build/latex working-directory: ${{ inputs.doc_directory }}/_build/latex
path: '*'
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -25,6 +25,11 @@ name: Static Type Check
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -63,7 +68,7 @@ jobs:
StaticTypeCheck: StaticTypeCheck:
name: 👀 Check Static Typing using Python ${{ inputs.python_version }} name: 👀 Check Static Typing using Python ${{ inputs.python_version }}
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
@@ -82,19 +87,20 @@ jobs:
run: ${{ inputs.commands }} run: ${{ inputs.commands }}
- name: 📤 Upload 'Static Typing Report' HTML artifact - name: 📤 Upload 'Static Typing Report' HTML artifact
uses: pyTooling/upload-artifact@v4
if: ${{ inputs.html_artifact != '' }} if: ${{ inputs.html_artifact != '' }}
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.html_artifact }} name: ${{ inputs.html_artifact }}
path: ${{ inputs.html_report }} working-directory: ${{ inputs.html_report }}
path: '*'
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1
- name: 📤 Upload 'Static Typing Report' JUnit artifact - name: 📤 Upload 'Static Typing Report' JUnit artifact
uses: pyTooling/upload-artifact@v4
if: ${{ inputs.junit_artifact != '' }} if: ${{ inputs.junit_artifact != '' }}
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4
with: with:
name: ${{ inputs.junit_artifact }} name: ${{ inputs.junit_artifact }}
path: ${{ inputs.junit_report }} path: ${{ inputs.junit_report }}

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
@@ -147,6 +162,9 @@ jobs:
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
lfs: true
submodules: true
# Package Manager steps # Package Manager steps
- name: 🔧 Install homebrew dependencies on macOS - name: 🔧 Install homebrew dependencies on macOS
@@ -207,7 +225,7 @@ jobs:
packages = { packages = {
"coverage": "python-coverage:p", "coverage": "python-coverage:p",
"docstr_coverage": "python-pyyaml:p", "docstr_coverage": "python-pyaml:p",
"igraph": "igraph:p", "igraph": "igraph:p",
"jinja2": "python-markupsafe:p", "jinja2": "python-markupsafe:p",
"lxml": "python-lxml:p", "lxml": "python-lxml:p",
@@ -215,12 +233,13 @@ jobs:
"markupsafe": "python-markupsafe:p", "markupsafe": "python-markupsafe:p",
"pip": "python-pip:p", "pip": "python-pip:p",
"pyyaml": "python-pyyaml:p", "pyyaml": "python-pyyaml:p",
"ruamel.yaml": "python-ruamel-yaml:p python-ruamel.yaml.clib:p", "ruamel.yaml": "python-ruamel-yaml:p",
# "ruamel.yaml": "python-ruamel-yaml:p python-ruamel.yaml.clib:p",
"sphinx": "python-markupsafe:p", "sphinx": "python-markupsafe:p",
"tomli": "python-tomli:p", "tomli": "python-tomli:p",
"wheel": "python-wheel:p", "wheel": "python-wheel:p",
"pyEDAA.ProjectModel": "python-ruamel-yaml:p python-ruamel.yaml.clib:p python-lxml:p", "pyedaa.projectmodel": "python-ruamel-yaml:p python-ruamel.yaml.clib:p python-lxml:p",
"pyEDAA.Reports": "python-ruamel-yaml:p python-ruamel.yaml.clib:p python-lxml:p", "pyedaa.reports": "python-ruamel-yaml:p python-ruamel.yaml.clib:p python-lxml:p",
} }
subPackages = { subPackages = {
"pytooling": { "pytooling": {
@@ -263,8 +282,8 @@ jobs:
# Python setup # Python setup
- name: '🟦 Setup MSYS2 for ${{ matrix.runtime }}' - name: '🟦 Setup MSYS2 for ${{ matrix.runtime }}'
if: matrix.system == 'msys2'
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
if: matrix.system == 'msys2'
with: with:
msystem: ${{ matrix.runtime }} msystem: ${{ matrix.runtime }}
update: true update: true
@@ -273,8 +292,8 @@ jobs:
${{ inputs.pacboy }} ${{ inputs.pacboy }}
- name: 🐍 Setup Python ${{ matrix.python }} - name: 🐍 Setup Python ${{ matrix.python }}
if: matrix.system != 'msys2'
uses: actions/setup-python@v5 uses: actions/setup-python@v5
if: matrix.system != 'msys2'
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
@@ -319,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)
@@ -391,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
@@ -407,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 }}
@@ -430,25 +386,26 @@ 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
uses: pyTooling/upload-artifact@v4
if: inputs.unittest_xml_artifact != '' if: inputs.unittest_xml_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/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 }}
path: report/unit/TestReportSummary.xml working-directory: ${{ inputs.unittest_report_xml_directory }}
path: ${{ inputs.unittest_report_xml_filename }}
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1
# - name: 📤 Upload 'Unit Tests HTML Report' artifact # - name: 📤 Upload 'Unit Tests HTML Report' artifact
# if: inputs.unittest_html_artifact != '' # if: inputs.unittest_html_artifact != ''
# continue-on-error: true # continue-on-error: true
# uses: actions/upload-artifact@v4 # uses: pyTooling/upload-artifact@v4
# with: # with:
# name: ${{ inputs.unittest_html_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} # name: ${{ inputs.unittest_html_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
# path: ${{ steps.getVariables.outputs.unittest_report_html_directory }} # path: ${{ steps.getVariables.outputs.unittest_report_html_directory }}
@@ -458,7 +415,7 @@ jobs:
- name: 📤 Upload 'Coverage SQLite Database' artifact - name: 📤 Upload 'Coverage SQLite Database' artifact
if: inputs.coverage_sqlite_artifact != '' if: inputs.coverage_sqlite_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_sqlite_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.coverage_sqlite_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: .coverage path: .coverage
@@ -469,7 +426,7 @@ jobs:
- name: 📤 Upload 'Coverage XML Report' artifact - name: 📤 Upload 'Coverage XML Report' artifact
if: inputs.coverage_xml_artifact != '' if: inputs.coverage_xml_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.coverage_xml_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: ${{ steps.getVariables.outputs.coverage_report_xml }} path: ${{ steps.getVariables.outputs.coverage_report_xml }}
@@ -479,7 +436,7 @@ jobs:
- name: 📤 Upload 'Coverage JSON Report' artifact - name: 📤 Upload 'Coverage JSON Report' artifact
if: inputs.coverage_json_artifact != '' if: inputs.coverage_json_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_json_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.coverage_json_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: ${{ steps.getVariables.outputs.coverage_report_json }} path: ${{ steps.getVariables.outputs.coverage_report_json }}
@@ -489,9 +446,10 @@ jobs:
- name: 📤 Upload 'Coverage HTML Report' artifact - name: 📤 Upload 'Coverage HTML Report' artifact
if: inputs.coverage_html_artifact != '' if: inputs.coverage_html_artifact != ''
continue-on-error: true continue-on-error: true
uses: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ inputs.coverage_html_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }} name: ${{ inputs.coverage_html_artifact }}-${{ matrix.system }}-${{ matrix.runtime }}-${{ matrix.python }}
path: ${{ steps.getVariables.outputs.coverage_report_html_directory }} working-directory: ${{ steps.getVariables.outputs.coverage_report_html_directory }}
path: '*'
if-no-files-found: error if-no-files-found: error
retention-days: 1 retention-days: 1

View File

@@ -25,6 +25,11 @@ name: Verify examples
on: on:
workflow_call: workflow_call:
inputs: inputs:
ubuntu_image_version:
description: 'Ubuntu image version.'
required: false
default: '24.04'
type: string
python_version: python_version:
description: 'Python version.' description: 'Python version.'
required: false required: false
@@ -35,7 +40,7 @@ jobs:
VerifyDocs: VerifyDocs:
name: 👍 Verify example snippets using Python ${{ inputs.python_version }} name: 👍 Verify example snippets using Python ${{ inputs.python_version }}
runs-on: ubuntu-24.04 runs-on: "ubuntu-${{ inputs.ubuntu_image_version }}"
steps: steps:
- name: ⏬ Checkout repository - name: ⏬ Checkout repository

View File

@@ -6,10 +6,10 @@ on:
jobs: jobs:
Params: Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
python_version_list: "3.10 3.11" python_version_list: "3.12 3.13"
system_list: "ubuntu windows" system_list: "ubuntu windows"
Testing: Testing:
@@ -22,10 +22,10 @@ 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: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }}-${{ matrix.system }}-${{ matrix.python }} name: ${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }}-${{ matrix.system }}-${{ matrix.python }}
path: artifact.txt path: artifact.txt
@@ -39,10 +39,10 @@ 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: actions/upload-artifact@v4 uses: pyTooling/upload-artifact@v4
with: with:
name: ${{ fromJson(needs.Params.outputs.artifact_names).package_all }} name: ${{ fromJson(needs.Params.outputs.artifact_names).package_all }}
path: package.txt path: package.txt
@@ -50,7 +50,7 @@ jobs:
retention-days: 1 retention-days: 1
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r1 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@main
needs: needs:
- Params - Params
- Testing - Testing

View File

@@ -1,128 +1,172 @@
name: Verification of Complete Pipeline name: Verification of Job Templates
on: on:
push: push:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
ConfigParams:
uses: pyTooling/Actions/.github/workflows/ExtractConfiguration.yml@main
with:
package_name: pyDummy
UnitTestingParams: UnitTestingParams:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: pyDummy name: pyDummy
python_version_list: "3.8 3.9 3.10 3.11 3.12 pypy-3.8 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@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
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@r1 uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@main
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@r1 uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@main
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@r1 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@r1 uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@main
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
with: with:
python_version: ${{ needs.UnitTestingParams.outputs.python_version }} python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
commands: | commands: |
mypy --html-report htmlmypy -p pyDummy ${{ needs.ConfigParams.outputs.mypy_prepare_command }}
mypy --html-report htmlmypy -p ${{ needs.ConfigParams.outputs.package_fullname }}
html_report: 'htmlmypy' html_report: 'htmlmypy'
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }} html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).statictyping_html }}
PublishCoverageResults: DocCoverage:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@r1 uses: pyTooling/Actions/.github/workflows/CheckDocumentation.yml@main
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
- UnitTesting
- PlatformTesting
# - Coverage
with: with:
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }} python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }} directory: ${{ needs.ConfigParams.outputs.package_directors }}
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }} # fail_below: 70
coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@dev
needs:
- UnitTesting
- PlatformTesting
with:
additional_merge_args: '-d "--pytest=rewrite-dunder-init;reduce-depth:pytest.tests.unit;reduce-depth:pytest.tests.platform"'
Package: Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@r1 uses: pyTooling/Actions/.github/workflows/Package.yml@main
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:
uses: pyTooling/Actions/.github/workflows/PublishCoverageResults.yml@main
needs:
- UnitTestingParams
- UnitTesting
- PlatformTesting
with:
coverage_sqlite_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}
coverage_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_xml }}
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
coverage_html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_html }}
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@main
needs:
- UnitTestingParams
- UnitTesting
- PlatformTesting
with:
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@r1 # uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@main
# needs: # needs:
# - UnitTestingParams # - UnitTestingParams
# with: # with:
# python_version: ${{ needs.UnitTestingParams.outputs.python_version }} # python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
BuildTheDocs: Documentation:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@r1 uses: pyTooling/Actions/.github/workflows/SphinxDocumentation.yml@main
needs: needs:
- ConfigParams
- UnitTestingParams - UnitTestingParams
- PublishTestResults
- PublishCoverageResults
# - VerifyDocs # - VerifyDocs
with: with:
artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }} python_version: ${{ needs.UnitTestingParams.outputs.python_version }}
coverage_report_json_directory: ${{ needs.ConfigParams.outputs.coverage_report_json_directory }}
unittest_xml_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}
coverage_json_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_json }}
html_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_html }}
latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
PublishToGitHubPages: IntermediateCleanUp:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@r1 uses: pyTooling/Actions/.github/workflows/IntermediateCleanUp.yml@main
needs: needs:
- UnitTestingParams - UnitTestingParams
- BuildTheDocs - PublishCoverageResults
# - Coverage - PublishTestResults
- Documentation
with:
sqlite_coverage_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).codecoverage_sqlite }}-
xml_unittest_artifacts_prefix: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).unittesting_xml }}-
PDFDocumentation:
uses: pyTooling/Actions/.github/workflows/LaTeXDocumentation.yml@main
needs:
- UnitTestingParams
- Documentation
with:
document: Actions
latex_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_latex }}
pdf_artifact: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).documentation_pdf }}
PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@main
needs:
- UnitTestingParams
- Documentation
- PDFDocumentation
- PublishCoverageResults - PublishCoverageResults
- StaticTypeCheck - StaticTypeCheck
with: with:
@@ -131,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@r1 uses: pyTooling/Actions/.github/workflows/Release.yml@main
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@r1 uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@main
if: startsWith(github.ref, 'refs/tags') if: startsWith(github.ref, 'refs/tags')
needs: needs:
- UnitTestingParams - UnitTestingParams
@@ -156,24 +199,24 @@ jobs:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }} PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
ArtifactCleanUp: ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@r1 uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@main
needs: needs:
- UnitTestingParams - UnitTestingParams
- PlatformTestingParams - PlatformTestingParams
- UnitTesting - UnitTesting
- PlatformTesting
# - Coverage
- StaticTypeCheck - StaticTypeCheck
# - BuildTheDocs - PlatformTesting
- PublishToGitHubPages - Documentation
- PublishCoverageResults - PDFDocumentation
- PublishTestResults - PublishTestResults
- PublishCoverageResults
- PublishToGitHubPages
- IntermediateCleanUp
with: with:
package: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }} package: ${{ fromJson(needs.UnitTestingParams.outputs.artifact_names).package_all }}
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 }}-*
@@ -185,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

@@ -0,0 +1,15 @@
name: Verification of Pipeline Templates (Namespace Package)
on:
push:
workflow_dispatch:
jobs:
NamespacePackage:
uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@main
with:
package_namespace: pyExamples
package_name: Extensions
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}

123
.github/workflows/_Checking_Nightly.yml vendored Normal file
View File

@@ -0,0 +1,123 @@
name: Verification of Nightly Releases
on:
push:
workflow_dispatch:
jobs:
Build:
name: Build something
runs-on: ubuntu-24.04
steps:
- name: 🖉 Build 1
run: |
printf "%s\n" "Document 1 $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt
printf "%s\n" "Analysis log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > analysis.log
printf "%s\n" "Build log $(date --utc '+%d.%m.%Y - %H:%M:%S')" > build.log
- name: 📤 Upload artifact
uses: pyTooling/upload-artifact@v4
with:
name: document
path: |
document1.txt
*.log
if-no-files-found: error
retention-days: 1
- name: 🖉 Program
run: |
printf "%s\n" "Document other $(date --utc '+%d.%m.%Y - %H:%M:%S')" > document1.txt
printf "%s\n" "Program $(date --utc '+%d.%m.%Y - %H:%M:%S')" > program.py
- name: 📤 Upload artifact
uses: actions/upload-artifact@v4
with:
name: other
path: |
*.txt
*.py
if-no-files-found: error
retention-days: 1
NightlyPage:
uses: pyTooling/Actions/.github/workflows/NightlyRelease.yml@main
needs:
- Build
secrets: inherit
permissions:
contents: write
actions: write
# attestations: write
with:
can-fail: true
prerelease: true
replacements: |
version=4.2.0
tool=myTool
prog=program
nightly_title: "Nightly Test Release"
nightly_description: |
This *nightly* release contains all latest and important artifacts created by %tool%'s CI pipeline.
# %tool% %version%
* %prog%
assets: |
document: document1.txt: Documentation
document: build.log: Logfile - %tool% - %tool%
other: document1.txt: SBOM - %version%
other: %prog%.py: 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
NightlyPageWithInventory:
uses: ./.github/workflows/NightlyRelease.yml
needs:
- Build
secrets: inherit
permissions:
contents: write
actions: write
# attestations: write
with:
can-fail: true
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: |
# artifact: file: labels: asset title
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,54 +6,54 @@ on:
jobs: jobs:
Params_Default: Params_Default:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
Params_PythonVersions: Params_PythonVersions:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
python_version_list: "3.9 3.10 pypy-3.8 pypy-3.9" python_version_list: "3.11 3.12 pypy-3.9 pypy-3.10"
Params_Systems: Params_Systems:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
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@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
python_version_list: "3.10" python_version_list: "3.11"
system_list: "ubuntu windows macos" system_list: "ubuntu windows macos macos-arm"
include_list: "ubuntu:3.11 ubuntu:3.12" include_list: "ubuntu:3.12 ubuntu:3.13"
Params_Exclude: Params_Exclude:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
python_version_list: "3.10" python_version_list: "3.12"
system_list: "ubuntu windows macos" system_list: "ubuntu windows macos macos-arm"
exclude_list: "windows:3.10 windows:3.11" exclude_list: "windows:3.12 windows:3.13"
Params_Disable: Params_Disable:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
python_version_list: "3.10" python_version_list: "3.12"
system_list: "ubuntu windows macos" system_list: "ubuntu windows macos macos-arm"
disable_list: "windows:3.10 windows:3.11" disable_list: "windows:3.12 windows:3.13"
Params_All: Params_All:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@r1 uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with: with:
name: Example name: Example
python_version_list: "3.10 3.11" python_version_list: "3.12 3.13"
system_list: "ubuntu windows macos" system_list: "ubuntu windows macos macos-arm"
include_list: "windows:3.8 windows:3.9 windows:3.12" include_list: "windows:3.10 windows:3.11 windows:3.13"
exclude_list: "macos:3.10 macos:3.11" exclude_list: "macos:3.12 macos:3.13"
Params_Check: Params_Check:
needs: needs:
@@ -80,12 +80,10 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.8", "3.9", "3.10", "3.11", "3.12"] expectedPythons = ["3.9", "3.10", "3.11", "3.12", "3.13"]
expectedSystems = ["ubuntu", "windows", "macos"] 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"]
expectedJobs.remove("macos:3.8")
expectedJobs.remove("macos:3.9")
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
"unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML", "unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML",
@@ -116,7 +114,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")
@@ -142,13 +143,10 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.9", "3.10", "pypy-3.8", "pypy-3.9"] expectedPythons = ["3.11", "3.12", "pypy-3.9", "pypy-3.10"]
expectedSystems = ["ubuntu", "windows", "macos"] 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"]
expectedJobs.remove("macos:3.9")
expectedJobs.remove("macos:pypy-3.8")
expectedJobs.remove("macos:pypy-3.9")
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
"unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML", "unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML",
@@ -179,7 +177,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")
@@ -205,10 +206,10 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.8", "3.9", "3.10", "3.11", "3.12"] 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",
@@ -239,7 +240,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")
@@ -265,9 +269,9 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.10"] expectedPythons = ["3.12"]
expectedSystems = ["ubuntu", "windows", "macos"] expectedSystems = ["ubuntu", "windows", "macos", "macos-arm"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["ubuntu:3.11", "ubuntu:3.12"] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["ubuntu:3.11", "ubuntu:3.12"]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
@@ -299,7 +303,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")
@@ -325,9 +332,9 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.10"] expectedPythons = ["3.12"]
expectedSystems = ["ubuntu", "macos"] expectedSystems = ["ubuntu", "macos", "macos-arm"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
@@ -359,7 +366,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")
@@ -385,9 +395,9 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.10"] expectedPythons = ["3.12"]
expectedSystems = ["ubuntu", "macos"] expectedSystems = ["ubuntu", "macos", "macos-arm"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
@@ -419,7 +429,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")
@@ -445,10 +458,10 @@ jobs:
from pyTooling.Common import zipdicts from pyTooling.Common import zipdicts
expectedPythonVersion = "3.12" expectedPythonVersion = "3.13"
expectedPythons = ["3.10", "3.11"] expectedPythons = ["3.12", "3.13"]
expectedSystems = ["ubuntu", "windows"] expectedSystems = ["ubuntu", "macos-arm", "windows"]
expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["windows:3.8", "windows:3.9", "windows:3.12"] expectedJobs = [f"{system}:{python}" for system in expectedSystems for python in expectedPythons] + ["windows:3.10", "windows:3.11", "windows:3.13"]
expectedName = "Example" expectedName = "Example"
expectedArtifacts = { expectedArtifacts = {
"unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML", "unittesting_xml": f"{expectedName}-UnitTestReportSummary-XML",
@@ -479,7 +492,10 @@ jobs:
print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.") print(f"Number of 'python_jobs' does not match: {len(actualPythonJobs)} != {len(expectedJobs)}.")
print("Actual jobs:") print("Actual jobs:")
for job in actualPythonJobs: for job in actualPythonJobs:
print(f" {job['system']}:{job['python']}") if job['system'] == "msys2":
print(f" {job['runtime'].lower()}:{job['python']}")
else:
print(f" {job['system']}:{job['python']}")
print("Expected jobs:") print("Expected jobs:")
for job in expectedJobs: for job in expectedJobs:
print(f" {job}") print(f" {job}")

View File

@@ -0,0 +1,14 @@
name: Verification of Pipeline Templates (Simple Package)
on:
push:
workflow_dispatch:
jobs:
SimplePackage:
uses: pyTooling/Actions/.github/workflows/CompletePipeline.yml@main
with:
package_name: pyDummy
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }}

2
.gitignore vendored
View File

@@ -31,7 +31,7 @@ doc/pyDummy/**/*.*
# BuildTheDocs # BuildTheDocs
doc/_theme/**/*.* doc/_theme/**/*.*
# IntelliJ project files # PyCharm project files
/.idea/workspace.xml /.idea/workspace.xml
# Git files # Git files

2
.idea/Actions.iml generated
View File

@@ -2,7 +2,7 @@
<module type="PYTHON_MODULE" version="4"> <module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" /> <content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" /> <orderEntry type="jdk" jdkName="Python 3.13" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
</component> </component>
</module> </module>

View File

@@ -1,178 +0,0 @@
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# Unai Martinez-Corral #
# #
# ==================================================================================================================== #
# Copyright 2020-2024 The pyTooling Authors #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
name: Pipeline
on:
workflow_dispatch:
jobs:
# This job is a workaround for global variables
# See https://github.com/actions/runner/issues/480
Params:
uses: pyTooling/Actions/.github/workflows/Parameters.yml@main
with:
name: ToolName
# Optional
system_list: 'ubuntu windows msys2 macos'
python_version: '3.10'
python_version_list: '3.8 3.9 3.10'
UnitTesting:
uses: pyTooling/Actions/.github/workflows/UnitTesting.yml@main
needs:
- Params
with:
jobs: ${{ needs.Params.outputs.python_jobs }}
# Optional
requirements: '-r tests/requirements.txt'
pacboy: >-
python-pip:p
python-wheel:p
python-coverage:p
python-lxml:p
mingw_requirements: '-r tests/requirements.mingw.txt'
tests_directory: 'tests'
unittest_directory: 'unit'
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }}
Coverage:
uses: pyTooling/Actions/.github/workflows/CoverageCollection.yml@main
needs:
- Params
with:
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).codecoverage_html }}
# Optional
python_version: ${{ needs..Params.outputs.python_version }}
requirements: '-r tests/requirements.txt'
tests_directory: 'tests'
unittest_directory: 'unit'
secrets:
codacy_token: ${{ secrets.CODACY_PROJECT_TOKEN }}
StaticTypeCheck:
uses: pyTooling/Actions/.github/workflows/StaticTypeCheck.yml@main
needs:
- Params
with:
commands: |
mypy --junit-xml StaticTypingSummary.xml --html-report htmlmypy -p ToolName
html_artifact: ${{ fromJson(needs.Params.outputs.artifact_names).statictyping_html }}
junit_artifact: ${{ fromJson(needs.Params.outputs.artifact_names).statictyping_junit }}
# Optional
python_version: ${{ needs..Params.outputs.python_version }}
requirements: '-r tests/requirements.txt'
html_report: 'htmlmypy'
junit_report: 'StaticTypingSummary.xml'
allow_failure: true
PublishTestResults:
uses: pyTooling/Actions/.github/workflows/PublishTestResults.yml@main
needs:
- UnitTesting
- StaticTypeCheck
with:
# Optional
report_files: artifacts/**/*.xml
Package:
uses: pyTooling/Actions/.github/workflows/Package.yml@main
needs:
- Params
- Coverage
with:
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).package_all }}
# Optional
python_version: ${{ needs..Params.outputs.python_version }}
requirements: 'wheel'
Release:
uses: pyTooling/Actions/.github/workflows/Release.yml@main
if: startsWith(github.ref, 'refs/tags')
needs:
- UnitTesting
- Coverage
- StaticTypeCheck
- Package
PublishOnPyPI:
uses: pyTooling/Actions/.github/workflows/PublishOnPyPI.yml@main
if: startsWith(github.ref, 'refs/tags')
needs:
- Params
- Release
- Package
with:
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).package_all }}
# Optional
python_version: ${{ needs..Params.outputs.python_version }}
requirements: 'wheel twine'
secrets:
PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}
VerifyDocs:
uses: pyTooling/Actions/.github/workflows/VerifyDocs.yml@main
needs:
- Params
with:
# Optional
python_version: ${{ needs..Params.outputs.python_version }}
BuildTheDocs:
uses: pyTooling/Actions/.github/workflows/BuildTheDocs.yml@main
needs:
- Params
- VerifyDocs
with:
artifact: ${{ fromJson(needs.Params.outputs.artifact_names).documentation_html }}
PublishToGitHubPages:
uses: pyTooling/Actions/.github/workflows/PublishToGitHubPages.yml@main
needs:
- Params
- BuildTheDocs
- Coverage
- StaticTypeCheck
with:
doc: ${{ fromJson(needs.Params.outputs.artifact_names).documentation_html }}
# Optional
coverage: ${{ fromJson(needs.Params.outputs.artifact_names).codecoverage_html }}
typing: ${{ fromJson(needs.Params.outputs.artifact_names).statictyping_html }}
ArtifactCleanUp:
uses: pyTooling/Actions/.github/workflows/ArtifactCleanUp.yml@main
needs:
- Params
- PublishTestResults
- Coverage
- StaticTypeCheck
- BuildTheDocs
- PublishToGitHubPages
with:
package: ${{ fromJson(needs.Params.outputs.artifact_names).package_all }}
remaining: |
${{ fromJson(needs.Params.outputs.artifact_names).unittesting_xml }}-*
${{ fromJson(needs.Params.outputs.artifact_names).codecoverage_html }}
${{ fromJson(needs.Params.outputs.artifact_names).statictyping_html }}
${{ fromJson(needs.Params.outputs.artifact_names).statictyping_junit }}
${{ fromJson(needs.Params.outputs.artifact_names).documentation_html }}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

111
README.md
View File

@@ -10,52 +10,97 @@ 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
[ExamplePipeline.yml](ExamplePipeline.yml) is an example Workflow which uses all of the Reusable Workflows. ExamplePipeline.yml is an example Workflow which uses all of the Reusable Workflows.
Python package/tool developers can copy it into their repos, in order to use al the reusable workflows straightaway. Python package/tool developers can copy it into their repos, in order to use al the reusable workflows straightaway.
Minimal required modifications are the following: Minimal required modifications are the following:

View File

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

View File

@@ -44,7 +44,7 @@ Complex Example
The following instantiation example creates 3 jobs from the same template, but with differing input parameters. The The following instantiation example creates 3 jobs from the same template, but with differing input parameters. The
first job `UnitTestingParams` might be used to create a job matrix of unit tests. It creates the cross of default first job `UnitTestingParams` might be used to create a job matrix of unit tests. It creates the cross of default
systems (Windows, Ubuntu, MacOS, MinGW64, UCRT64) and the given list of Python versions including some mypy versions. In systems (Windows, Ubuntu, macOS, MinGW64, UCRT64) and the given list of Python versions including some mypy versions. In
addition a list of excludes (marked as :deletion:`deletions`) and includes (marked as :addition:`additions`) is handed addition a list of excludes (marked as :deletion:`deletions`) and includes (marked as :addition:`additions`) is handed
over resulting in the following combinations: over resulting in the following combinations:
@@ -55,7 +55,7 @@ over resulting in the following combinations:
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+ +------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| Ubuntu 🐧 | ubuntu:3.8 | ubuntu:3.9 | ubuntu:3.10 | ubuntu:3.11 | :addition:`ubuntu:3.12` | | | ubuntu:pypy-3.9 | ubuntu:pypy-3.10 | | Ubuntu 🐧 | ubuntu:3.8 | ubuntu:3.9 | ubuntu:3.10 | ubuntu:3.11 | :addition:`ubuntu:3.12` | | | ubuntu:pypy-3.9 | ubuntu:pypy-3.10 |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+ +------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| MacOS 🍎 | macos:3.8 | macos:3.9 | macos:3.10 | macos:3.11 | :addition:`macos:3.12` | | | macos:pypy-3.9 | macos:pypy-3.10 | | macOS 🍎 | macos:3.8 | macos:3.9 | macos:3.10 | macos:3.11 | :addition:`macos:3.12` | | | macos:pypy-3.9 | macos:pypy-3.10 |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+ +------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
| MSYS 🟪 | | | | | | | | | | | MSYS 🟪 | | | | | | | | | |
+------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+ +------------+-------------+-------------+--------------+--------------+-------------------------+------------+-------------+------------------------------+-------------------------------+
@@ -138,7 +138,7 @@ python_version_list
| Parameter Name | Required | Type | Default | | Parameter Name | Required | Type | Default |
+======================+==========+==========+============================+ +======================+==========+==========+============================+
| python_version_list | optional | string | ``3.8 3.9 3.10 3.11 3.12`` | | python_version_list | optional | string | ``3.8 3.9 3.10 3.11 3.12`` |
+----------------------+----------+----------+-------------------------- -+ +----------------------+----------+----------+----------------------------+
Space separated list of CPython versions and/or mypy version to run tests with. Space separated list of CPython versions and/or mypy version to run tests with.
@@ -197,7 +197,7 @@ Space separated list of systems to run tests on.
+------+-----------+------------------------------+-----------------------------------------------------------------+ +------+-----------+------------------------------+-----------------------------------------------------------------+
| 🐧 | Ubuntu | Ubuntu 22.04 (LTS) (latest) | | | 🐧 | Ubuntu | Ubuntu 22.04 (LTS) (latest) | |
+------+-----------+------------------------------+-----------------------------------------------------------------+ +------+-----------+------------------------------+-----------------------------------------------------------------+
| 🍎 | MacOS | macOS Monterey 12 (latest) | While this marked latest, macOS Ventura 13 is already provided. | | 🍎 | macOS | macOS Monterey 12 (latest) | While this marked latest, macOS Ventura 13 is already provided. |
+------+-----------+------------------------------+-----------------------------------------------------------------+ +------+-----------+------------------------------+-----------------------------------------------------------------+
| 🟪 | MSYS | | | | 🟪 | MSYS | | |
+------+-----------+------------------------------+-----------------------------------------------------------------+ +------+-----------+------------------------------+-----------------------------------------------------------------+

115
doc/_static/css/override.css vendored Normal file
View File

@@ -0,0 +1,115 @@
/* theme overrides */
.rst-content h1,
.rst-content h2 {
margin-top: 24px;
margin-bottom: 6px;
text-decoration: underline;
}
.rst-content h3,
.rst-content h4,
.rst-content h5,
.rst-content h6 {
margin-top: 12px;
margin-bottom: 6px;
}
.rst-content p {
margin-bottom: 6px
}
/* general overrides */
html {
font-size: 15px;
}
footer {
font-size: 95%;
text-align: center
}
footer p {
margin-bottom: 0px /* 12px */;
font-size: 95%
}
section > p,
.section p,
.simple li {
text-align: justify
}
.rst-content .topic-title {
font-size: larger;
font-weight: 700;
margin-top: 18px;
margin-bottom: 6px;
}
.rst-content p.rubric {
text-decoration: underline;
font-weight: 700;
margin-top: 18px;
margin-bottom: 16px;
}
/* wyrm overrides */
.wy-menu-vertical header,
.wy-menu-vertical p.caption {
color: #9b9b9b /* #55a5d9 */;
padding: 0 0.809em /* 0 1.618em */;
margin: 6px 0 0 0 /* 12px 0 0 */;
border-top: 1px solid #9b9b9b;
}
.wy-side-nav-search {
margin-bottom: 0 /* .809em */;
background-color: #333333 /* #2980b9 */;
/* BTD: */
/*color: #fcfcfc*/
}
.wy-side-nav-search input[type=text] {
border-radius: 0px /* 50px */;
}
.wy-side-nav-search .wy-dropdown > a, .wy-side-nav-search > a {
/* BTD: */
/*color: #fcfcfc;*/
margin-bottom: 0.404em /* .809em */;
}
.wy-side-nav-search > div.version {
margin: 0 0 6px 0;
/* BTD: */
/*margin-top: -.4045em;*/
}
.wy-nav .wy-menu-vertical a:hover {
background-color: #333333 /* #2980b9 */;
}
.wy-nav-content {
max-width: 1600px /* 800px */ ;
}
.wy-nav-top {
background: #333333 /* #2980b9 */;
}
/* Sphinx Design */
.sd-tab-set {
margin: 0
}
.sd-tab-set > label {
padding-top: .5em;
padding-right: 1em;
padding-bottom: .5em;
padding-left: 1em
}
.sd-container-fluid {
padding-left: 0;
padding-right: 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

View File

@@ -14,7 +14,7 @@ ROOT = Path(__file__).resolve().parent
sys_path.insert(0, abspath(".")) sys_path.insert(0, abspath("."))
sys_path.insert(0, abspath("..")) sys_path.insert(0, abspath(".."))
sys_path.insert(0, abspath("../pyDummy")) sys_path.insert(0, abspath("../pyDummy"))
sys_path.insert(0, abspath("_extensions")) # sys_path.insert(0, abspath("_extensions"))
# ============================================================================== # ==============================================================================
@@ -23,9 +23,11 @@ sys_path.insert(0, abspath("_extensions"))
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
# built documents. # built documents.
project = "Actions" githubNamespace = "pyTooling"
githubProject = "Actions"
project = "pyDummy"
packageInformationFile = Path(f"../pyDummy/__init__.py") packageInformationFile = Path(f"../{project}/__init__.py")
versionInformation = extractVersionInformation(packageInformationFile) versionInformation = extractVersionInformation(packageInformationFile)
author = versionInformation.Author author = versionInformation.Author
@@ -73,30 +75,15 @@ except Exception as ex:
# ============================================================================== # ==============================================================================
# Options for HTML output # Options for HTML output
# ============================================================================== # ==============================================================================
html_context = {} html_theme = "sphinx_rtd_theme"
ctx = ROOT / "context.json" html_theme_options = {
if ctx.is_file(): "logo_only": True,
html_context.update(loads(ctx.open('r').read())) "vcs_pageview_mode": 'blob',
"navigation_depth": 5,
if (ROOT / "_theme").is_dir(): }
html_theme_path = ["."] html_css_files = [
html_theme = "_theme" 'css/override.css',
html_theme_options = { ]
"logo_only": True,
"home_breadcrumbs": False,
"vcs_pageview_mode": 'blob',
# "body_max_width": None
# "navigation_depth": 5,
}
elif find_spec("sphinx_rtd_theme") is not None:
html_theme = "sphinx_rtd_theme"
html_theme_options = {
"logo_only": True,
"vcs_pageview_mode": 'blob',
# "navigation_depth": 5,
}
else:
html_theme = "alabaster"
# Add any paths that contain custom static files (such as style sheets) here, # Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files, # relative to this directory. They are copied after the builtin static files,
@@ -107,7 +94,7 @@ html_logo = str(Path(html_static_path[0]) / "logo.png")
html_favicon = str(Path(html_static_path[0]) / "icon.png") html_favicon = str(Path(html_static_path[0]) / "icon.png")
# Output file base name for HTML help builder. # Output file base name for HTML help builder.
htmlhelp_basename = "ActionsDoc" htmlhelp_basename = f"{githubProject}Doc"
# If not None, a 'Last updated on:' timestamp is inserted at every page # If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format. # bottom, using the given strftime format.
@@ -160,10 +147,10 @@ latex_elements = {
# author, documentclass [howto, manual, or own class]). # author, documentclass [howto, manual, or own class]).
latex_documents = [ latex_documents = [
( master_doc, ( master_doc,
"Actions.tex", f"{githubProject}.tex",
"The pyTooling Actions Documentation", f"The {githubProject} Documentation",
"Patrick Lehmann", f"Patrick Lehmann",
"manual" f"manual"
), ),
] ]
@@ -174,7 +161,6 @@ latex_documents = [
extensions = [ extensions = [
# Standard Sphinx extensions # Standard Sphinx extensions
"sphinx.ext.autodoc", "sphinx.ext.autodoc",
"sphinx.ext.coverage",
"sphinx.ext.extlinks", "sphinx.ext.extlinks",
"sphinx.ext.intersphinx", "sphinx.ext.intersphinx",
"sphinx.ext.inheritance_diagram", "sphinx.ext.inheritance_diagram",
@@ -186,10 +172,12 @@ extensions = [
# SphinxContrib extensions # SphinxContrib extensions
"sphinxcontrib.mermaid", "sphinxcontrib.mermaid",
# Other extensions # Other extensions
"sphinx_fontawesome", "sphinx_design",
"sphinx_copybutton",
"sphinx_autodoc_typehints", "sphinx_autodoc_typehints",
"sphinx_inline_tabs",
"autoapi.sphinx", "autoapi.sphinx",
"sphinx_reports",
# User defined extensions
] ]
@@ -221,11 +209,11 @@ autodoc_typehints = "both"
# Sphinx.Ext.ExtLinks # Sphinx.Ext.ExtLinks
# ============================================================================== # ==============================================================================
extlinks = { extlinks = {
"gh": ("https://GitHub.com/%s", "gh:%s"), "gh": (f"https://GitHub.com/%s", "gh:%s"),
"ghissue": ("https://GitHub.com/pyTooling/Actions/issues/%s", "issue #%s"), "ghissue": (f"https://GitHub.com/{githubNamespace}/{githubProject}/issues/%s", "issue #%s"),
"ghpull": ("https://GitHub.com/pyTooling/Actions/pull/%s", "pull request #%s"), "ghpull": (f"https://GitHub.com/{githubNamespace}/{githubProject}/pull/%s", "pull request #%s"),
"ghsrc": ("https://GitHub.com/pyTooling/Actions/blob/main/%s", None), "ghsrc": (f"https://GitHub.com/{githubNamespace}/{githubProject}/blob/main/%s", None),
"wiki": ("https://en.wikipedia.org/wiki/%s", None), "wiki": (f"https://en.wikipedia.org/wiki/%s", None),
} }
@@ -265,18 +253,53 @@ todo_link_only = True
# ============================================================================== # ==============================================================================
# Sphinx.Ext.Coverage # sphinx-reports
# ============================================================================== # ==============================================================================
coverage_show_missing_items = True # report_unittest_testsuites = {
# "src": {
# "name": f"{project}",
# "xml_report": "../report/unit/unittest.xml",
# }
# }
# report_codecov_packages = {
# "src": {
# "name": f"{project}",
# "json_report": "../report/coverage/coverage.json",
# "fail_below": 80,
# "levels": "default"
# }
# }
# report_doccov_packages = {
# "src": {
# "name": f"{project}",
# "directory": f"../{project}",
# "fail_below": 80,
# "levels": "default"
# }
# }
# ==============================================================================
# Sphinx_Design
# ==============================================================================
# sd_fontawesome_latex = True
# ============================================================================== # ==============================================================================
# AutoAPI.Sphinx # AutoAPI.Sphinx
# ============================================================================== # ==============================================================================
autoapi_modules = { autoapi_modules = {
"pyDummy": { f"{project}": {
"template": "module", "template": "package",
"output": "pyDummy", "output": project,
"override": True "override": True
} }
} }
for directory in [mod for mod in Path(f"../{project}").iterdir() if mod.is_dir() and mod.name != "__pycache__"]:
print(f"Adding module rule for '{project}.{directory.name}'")
autoapi_modules[f"{project}.{directory.name}"] = {
"template": "module",
"output": project,
"override": True
}

View File

@@ -3,5 +3,5 @@ Code Coverage Report
Code coverage report generated with `pytest <https://github.com/pytest-dev/pytest>`__ and `Coverage.py <https://github.com/nedbat/coveragepy/tree/master>`__. Code coverage report generated with `pytest <https://github.com/pytest-dev/pytest>`__ and `Coverage.py <https://github.com/nedbat/coveragepy/tree/master>`__.
.. report:code-coverage:: .. #report:code-coverage::
:packageid: src :packageid: src

View File

@@ -1,20 +1,19 @@
-r ../requirements.txt -r ../requirements.txt
pyTooling ~= 6.6 pyTooling ~= 8.2
# Enforce latest version on ReadTheDocs # Enforce latest version on ReadTheDocs
sphinx ~= 7.4 sphinx ~= 8.2
docutils ~= 0.20 docutils ~= 0.21
docutils_stubs ~= 0.0.22
# ReadTheDocs Theme
sphinx_rtd_theme ~= 3.0
# Sphinx Extenstions # Sphinx Extenstions
#sphinx.ext.coverage sphinxcontrib-mermaid ~= 1.0
#sphinxcontrib-actdiag>=0.8.5
sphinxcontrib-mermaid>=0.9.2
#sphinxcontrib-seqdiag>=0.8.5
#sphinxcontrib-textstyle>=0.2.1
#sphinxcontrib-spelling>=2.2.0
autoapi >= 2.0.1 autoapi >= 2.0.1
sphinx_fontawesome >= 0.0.6 sphinx_design ~= 0.6.1
sphinx-inline-tabs >= 2023.4.21 sphinx-copybutton >= 0.5.2
sphinx_autodoc_typehints ~= 2.3 sphinx_autodoc_typehints ~= 3.1
# changelog>=0.3.5 sphinx_reports ~= 0.7

View File

@@ -4,21 +4,21 @@
# 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/pyTooling :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/pyTooling :target: https://GitHub.com/pyTooling/Actions
.. # Sourcecode license .. # Sourcecode license
.. |SHIELD:svg:pyTooling-src-license| image:: https://img.shields.io/pypi/l/pyTooling?longCache=true&style=flat-square&logo=Apache&label=code .. |SHIELD:svg:pyTooling-src-license| image:: https://img.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: 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

@@ -3,5 +3,5 @@ Unittest Summary Report
Unittest report generated with `pytest <https://github.com/pytest-dev/pytest>`__. Unittest report generated with `pytest <https://github.com/pytest-dev/pytest>`__.
.. report:unittest-summary:: .. #report:unittest-summary::
:reportid: src :reportid: src

View File

@@ -11,7 +11,7 @@
# # # #
# License: # # License: #
# ==================================================================================================================== # # ==================================================================================================================== #
# Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany # # Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany #
# # # #
# Licensed under the Apache License, Version 2.0 (the "License"); # # Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. # # you may not use this file except in compliance with the License. #
@@ -34,7 +34,7 @@ A module for a set of dummy classes.
__author__ = "Patrick Lehmann" __author__ = "Patrick Lehmann"
__email__ = "Paebbels@gmail.com" __email__ = "Paebbels@gmail.com"
__copyright__ = "2017-2024, Patrick Lehmann" __copyright__ = "2017-2025, Patrick Lehmann"
__license__ = "Apache License, Version 2.0" __license__ = "Apache License, Version 2.0"
__version__ = "0.4.4" __version__ = "0.4.4"
__keywords__ = ["GitHub Actions"] __keywords__ = ["GitHub Actions"]

View File

@@ -0,0 +1,101 @@
# ==================================================================================================================== #
# _____ _ _ _ _ _ #
# _ __ _ |_ _|__ ___ | (_)_ __ __ _ / \ ___| |_(_) ___ _ __ ___ #
# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` | / _ \ / __| __| |/ _ \| '_ \/ __| #
# | |_) | |_| || | (_) | (_) | | | | | | (_| |_ / ___ \ (__| |_| | (_) | | | \__ \ #
# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)_/ \_\___|\__|_|\___/|_| |_|___/ #
# |_| |___/ |___/ #
# ==================================================================================================================== #
# Authors: #
# Patrick Lehmann #
# #
# License: #
# ==================================================================================================================== #
# Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany #
# #
# Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. #
# You may obtain a copy of the License at #
# #
# http://www.apache.org/licenses/LICENSE-2.0 #
# #
# Unless required by applicable law or agreed to in writing, software #
# distributed under the License is distributed on an "AS IS" BASIS, #
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
# See the License for the specific language governing permissions and #
# limitations under the License. #
# #
# SPDX-License-Identifier: Apache-2.0 #
# ==================================================================================================================== #
#
"""
A module for a set of dummy classes.
"""
__author__ = "Patrick Lehmann"
__email__ = "Paebbels@gmail.com"
__copyright__ = "2017-2025, Patrick Lehmann"
__license__ = "Apache License, Version 2.0"
__version__ = "0.14.8"
__keywords__ = ["GitHub Actions"]
__issue_tracker__ = "https://GitHub.com/pyTooling/Actions/issues"
from pyTooling.Decorators import export, readonly
from pyTooling.Platform import Platform
@export
class Base:
"""
A base-class for dummy applications.
"""
_value: int #: An internal value.
def __init__(self) -> None:
"""
Initializes the base-class.
"""
self._value = 0
@readonly
def Value(self) -> int:
"""
Read-only property to return the internal value.
:return: Internal value.
"""
return self._value
@export
class Application(Base):
"""
A dummy application for demonstration purposes.
"""
def __init__(self) -> None:
"""
Initializes the dummy application.
"""
super().__init__()
platform = Platform()
if platform.IsNativeLinux:
self._value += 1
elif platform.IsNativeMacOS:
self._value += 2
elif platform.IsNativeWindows:
self._value += 3
elif platform.IsMSYSOnWindows:
self._value += 11
elif platform.IsMinGW32OnWindows:
self._value += 12
elif platform.IsMinGW64OnWindows:
self._value += 13
elif platform.IsUCRT64OnWindows:
self._value += 14
elif platform.IsClang32OnWindows:
self._value += 15
elif platform.IsClang64OnWindows:
self._value += 16

View File

View File

@@ -1,8 +1,8 @@
[build-system] [build-system]
requires = [ requires = [
"setuptools ~= 75.1", "setuptools ~= 75.8",
"wheel ~= 0.44", "wheel ~= 0.45",
"pyTooling ~= 6.6" "pyTooling ~= 8.2"
] ]
build-backend = "setuptools.build_meta" build-backend = "setuptools.build_meta"
@@ -20,7 +20,11 @@ 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"
# Don't set 'python_classes = *' otherwise, pytest doesn't search for classes # Don't set 'python_classes = *' otherwise, pytest doesn't search for classes
# derived from unittest.Testcase # derived from unittest.Testcase
python_files = "*" python_files = "*"
@@ -29,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

@@ -1,4 +1,4 @@
FROM python:3.9-slim-bullseye FROM python:3.12-slim-bookworm
COPY releaser.py /releaser.py COPY releaser.py /releaser.py
RUN pip install PyGithub --progress-bar off \ RUN pip install PyGithub --progress-bar off \
&& apt update -qq \ && apt update -qq \

View File

@@ -1 +1 @@
pyTooling ~= 6.6 pyTooling ~= 8.2

316
run.ps1 Normal file
View File

@@ -0,0 +1,316 @@
[CmdletBinding()]
Param(
# Clean up all files and directories
[switch]$clean,
# Commands
[switch]$all,
[switch]$copyall,
[switch]$doc,
[switch]$livedoc,
[switch]$doccov,
[switch]$unit,
[switch]$liveunit,
[switch]$copyunit,
[switch]$cov,
[switch]$livecov,
[switch]$copycov,
[switch]$type,
[switch]$livetype,
[switch]$copytype,
[switch]$nooutput,
[switch]$build,
[switch]$install,
# Display this help"
[switch]$help
)
$PackageName = "Actions"
# set default values
$EnableDebug = [bool]$PSCmdlet.MyInvocation.BoundParameters["Debug"]
$EnableVerbose = [bool]$PSCmdlet.MyInvocation.BoundParameters["Verbose"] -or $EnableDebug
# Display help if no command was selected
$help = $help -or ( -not(
$all -or $copyall -or
$clean -or
$doc -or $livedoc -or $doccov -or
$unit -or $liveunit -or $copyunit -or
$cov -or $livecov -or $copycov -or
$type -or $livetype -or $copytype -or
$build -or $install
)
)
Write-Host "================================================================================" -ForegroundColor Magenta
Write-Host "$PackageName Documentation Compilation and Assembly Tool" -ForegroundColor Magenta
Write-Host "================================================================================" -ForegroundColor Magenta
if ($help)
{ Get-Help $MYINVOCATION.MyCommand.Path -Detailed
exit 0
}
if ($all)
{ $doc = $true
$unit = $true
# $copyunit = $true
$cov = $true
# $copycov = $true
$type = $true
$copytype = $true
}
if ($copyall)
{# $copyunit = $true
# $copycov = $true
$copytype = $true
}
if ($clean)
{ Write-Host -ForegroundColor DarkYellow "[live][DOC] Cleaning documentation directories ..."
rm -Force .\doc\$PackageName\*
.\doc\make.bat clean
Write-Host -ForegroundColor DarkYellow "[live][BUILD] Cleaning build directories ..."
rm -Force .\build\bdist.win-amd64
rm -Force .\build\lib
}
if ($build)
{ Write-Host -ForegroundColor Yellow "[live][BUILD] Cleaning build directories ..."
rm -Force .\build\bdist.win-amd64
rm -Force .\build\lib
Write-Host -ForegroundColor Yellow "[live][BUILD] Building $PackageName package as wheel ..."
py -3.13 -m build --wheel
Write-Host -ForegroundColor Yellow "[live][BUILD] Building wheel finished"
}
if ($install)
{ if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{ Write-Host -ForegroundColor Yellow "[live][INSTALL] Installing $PackageName with administrator rights ..."
$proc = Start-Process pwsh.exe "-NoProfile -ExecutionPolicy Bypass -WorkingDirectory `"$PSScriptRoot`" -File `"$PSCommandPath`" `"-install`"" -Verb RunAs -Wait
# Write-Host -ForegroundColor Yellow "[live][INSTALL] Wait on administrator console ..."
# Wait-Process -Id $proc.Id
}
else
{ Write-Host -ForegroundColor Cyan "[ADMIN][UNINSTALL] Uninstalling $PackageName ..."
py -3.13 -m pip uninstall -y $PackageName
Write-Host -ForegroundColor Cyan "[ADMIN][INSTALL] Installing $PackageName from wheel ..."
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 ..."
Start-Sleep -Seconds 5
}
}
$jobs = @()
if ($livedoc)
{ Write-Host -ForegroundColor DarkYellow "[live][DOC] Building documentation using Sphinx ..."
.\doc\make.bat html --verbose
Write-Host -ForegroundColor DarkYellow "[live][DOC] Documentation finished"
}
elseif ($doc)
{ Write-Host -ForegroundColor DarkYellow "[Job1][DOC] Building documentation using Sphinx ..."
Write-Host -ForegroundColor DarkGreen "[SCRIPT] Starting Documentation job ..."
# Compile documentation
$compileDocFunc = {
.\doc\make.bat html --verbose
}
$docJob = Start-Job -Name "Documentation" -ScriptBlock $compileDocFunc
# $jobs += $docJob
}
if ($doccov)
{
.\doc\make.bat coverage
}
if ($liveunit)
{ Write-Host -ForegroundColor DarkYellow "[live][UNIT] Running Unit Tests using pytest ..."
$env:ENVIRONMENT_NAME = "Windows (x86-64)"
pytest -raP --color=yes --junitxml=report/unit/unittest.xml --template=html1/index.html --report=report/unit/html/index.html --split-report tests/unit
if ($copyunit)
{ cp -Recurse -Force .\report\unit\html\* .\doc\_build\html\unittests
Write-Host -ForegroundColor DarkBlue "[live][UNIT] Copyed unit testing report to 'unittests' directory in HTML directory"
}
Write-Host -ForegroundColor DarkYellow "[live][UNIT] Unit Tests finished"
}
elseif ($unit)
{ Write-Host -ForegroundColor DarkYellow "[Job2][UNIT] Running Unit Tests using pytest ..."
Write-Host -ForegroundColor DarkGreen "[SCRIPT] Starting UnitTests jobs ..."
# Run unit tests
$runUnitFunc = {
$env:ENVIRONMENT_NAME = "Windows (x86-64)"
pytest -raP --color=yes --junitxml=report/unit/unittest.xml --template=html1/index.html --report=report/unit/html/index.html --split-report tests/unit
}
$unitJob = Start-Job -Name "UnitTests" -ScriptBlock $runUnitFunc
$jobs += $unitJob
}
if ($livecov)
{ Write-Host -ForegroundColor DarkMagenta "[live][COV] Running Unit Tests with coverage ..."
$env:ENVIRONMENT_NAME = "Windows (x86-64)"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -ra --tb=line --color=yes tests/unit
Write-Host -ForegroundColor DarkMagenta "[live][COV] Convert coverage report to HTML ..."
coverage html
Write-Host -ForegroundColor DarkMagenta "[live][COV] Convert coverage report to XML (Cobertura) ..."
coverage xml
Write-Host -ForegroundColor DarkMagenta "[live][COV] Convert coverage report to JSON ..."
coverage json
Write-Host -ForegroundColor DarkMagenta "[live][COV] Write coverage report to console ..."
coverage report
if ($copycov)
{ cp -Recurse -Force .\report\coverage\html\* .\doc\_build\html\coverage
Write-Host -ForegroundColor DarkMagenta "[live][COV] Copyed code coverage report to 'coverage' directory in HTML directory"
}
Write-Host -ForegroundColor DarkMagenta "[live][COV] Coverage finished"
}
elseif ($cov)
{ Write-Host -ForegroundColor DarkMagenta "[live][COV] Running Unit Tests with coverage ..."
Write-Host -ForegroundColor DarkMagenta "[SCRIPT] Starting Coverage jobs ..."
# Collect coverage
$collectCovFunc = {
$env:ENVIRONMENT_NAME = "Windows (x86-64)"
coverage run --data-file=.coverage --rcfile=pyproject.toml -m pytest -ra --tb=line --color=yes tests/unit
Write-Host -ForegroundColor DarkMagenta "[Job3][COV] Convert coverage report to HTML ..."
coverage html
Write-Host -ForegroundColor DarkMagenta "[Job3][COV] Convert coverage report to XML (Cobertura) ..."
coverage xml
Write-Host -ForegroundColor DarkMagenta "[Job3][COV] Convert coverage report to JSON ..."
coverage json
}
$covJob = Start-Job -Name "Coverage" -ScriptBlock $collectCovFunc
$jobs += $covJob
}
if ($livetype)
{ Write-Host -ForegroundColor DarkCyan "[live][TYPE] Running static type analysis using mypy ..."
$env:MYPY_FORCE_COLOR = 1
mypy.exe -p $PackageName
if ($copytype)
{ cp -Recurse -Force .\report\typing\* .\doc\_build\html\typing
Write-Host -ForegroundColor DarkCyan "[live][TYPE] Copyed typing report to 'typing' directory in HTML directory."
}
Write-Host -ForegroundColor DarkCyan "[live][TYPE] Static type analysis finished"
}
elseif ($type)
{ Write-Host -ForegroundColor DarkCyan "[live][TYPE] Running static type analysis using mypy ..."
Write-Host -ForegroundColor DarkCyan "[SCRIPT] Starting Typing jobs ..."
# Analyze types
$analyzeTypesFunc = {
$env:MYPY_FORCE_COLOR = 1
mypy.exe -p $PackageName
}
$typeJob = Start-Job -Name "Typing" -ScriptBlock $analyzeTypesFunc
$jobs += $typeJob
}
if ($doc)
{ Write-Host -ForegroundColor DarkGreen "[SCRIPT] Waiting on Documentation job ..."
Wait-Job -Job $docJob
Write-Host -ForegroundColor DarkYellow "[Job1][DOC] Documentation finished"
}
if ($jobs.Count -ne 0)
{
Write-Host -ForegroundColor DarkGreen ( "[SCRIPT] Waiting on {0} jobs ({1}) ..." -f $jobs.Count, (($jobs | %{ $_.Name }) -join ", "))
Wait-Job -Job $jobs
}
if (-not $liveunit -and $copyunit)
{
# if ($unit)
# { Wait-Job -Job $unitJob
# Write-Host -ForegroundColor DarkBlue "[Job2][UNIT] Unit tests finished"
# }
cp -Recurse -Force .\report\unit\html\* .\doc\_build\html\unittests
Write-Host -ForegroundColor DarkBlue "[post][UNIT] Copyed unit testing report to 'unittests' directory in HTML directory"
}
if (-not ($livecov -or $cov) -and $copycov)
{
# if ($cov)
# { Wait-Job -Job $unitJob
# Write-Host -ForegroundColor DarkMagenta "[Job3][UNIT] Coverage collection finished"
# }
cp -Recurse -Force .\report\coverage\html\* .\doc\_build\html\coverage
Write-Host -ForegroundColor DarkMagenta "[post][COV] Copyed code coverage report to 'coverage' directory in HTML directory"
}
if (-not $livetype -and $copytype)
{
# if ($type)
# { Wait-Job -Job $typeJob
# Write-Host -ForegroundColor DarkCyan "[Job4][UNIT] Static type analysis finished"
# }
cp -Recurse -Force .\report\typing\* .\doc\_build\html\typing
Write-Host -ForegroundColor DarkCyan "[post][TYPE] Copyed typing report to 'typing' directory in HTML directory."
}
if ($type)
{ Write-Host -ForegroundColor DarkCyan "================================================================================"
if (-not $nooutput)
{ Receive-Job -Job $typeJob
}
Remove-Job -Job $typeJob
}
if ($doc)
{ Write-Host -ForegroundColor DarkYellow "================================================================================"
if (-not $nooutput)
{ Receive-Job -Job $docJob
}
Remove-Job -Job $docJob
}
if ($unit)
{ Write-Host -ForegroundColor DarkBlue "================================================================================"
if (-not $nooutput)
{ Receive-Job -Job $unitJob
}
Remove-Job -Job $unitJob
}
if ($cov)
{ Write-Host -ForegroundColor DarkMagenta "================================================================================"
if (-not $nooutput)
{ Receive-Job -Job $covJob
}
Remove-Job -Job $covJob
if ($copycov)
{ cp -Recurse -Force .\report\coverage\html\* .\doc\_build\html\coverage
Write-Host -ForegroundColor DarkMagenta "[post][COV] Copyed code coverage report to 'coverage' directory in HTML directory"
}
}
Write-Host -ForegroundColor DarkGreen "================================================================================"
Write-Host -ForegroundColor DarkGreen "[SCRIPT] Finished"

View File

@@ -11,7 +11,7 @@
# # # #
# License: # # License: #
# ==================================================================================================================== # # ==================================================================================================================== #
# Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany # # Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany #
# # # #
# Licensed under the Apache License, Version 2.0 (the "License"); # # Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. # # you may not use this file except in compliance with the License. #

View File

@@ -8,7 +8,7 @@ print(f"Python: {version}")
def loadRequirementsFile(requirementsFile: Path): def loadRequirementsFile(requirementsFile: Path):
requirements = [] requirements = []
with requirementsFile.open("r") as file: with requirementsFile.open("r", encoding="utf-8") as file:
for line in file.readlines(): for line in file.readlines():
line = line.strip() line = line.strip()
if line.startswith("#") or line.startswith("https") or line == "": if line.startswith("#") or line.startswith("https") or line == "":
@@ -84,7 +84,7 @@ for dependency in dependencies:
# Write jobs to special file # Write jobs to special file
github_output = Path(getenv("GITHUB_OUTPUT")) github_output = Path(getenv("GITHUB_OUTPUT"))
print(f"GITHUB_OUTPUT: {github_output}") print(f"GITHUB_OUTPUT: {github_output}")
with github_output.open("a+") as f: with github_output.open("a+", encoding="utf-8") as f:
f.write(f"pacboy_packages={' '.join(pacboyPackages)}\n") f.write(f"pacboy_packages={' '.join(pacboyPackages)}\n")
print(f"GITHUB_OUTPUT:") print(f"GITHUB_OUTPUT:")

View File

@@ -11,7 +11,7 @@
# # # #
# License: # # License: #
# ==================================================================================================================== # # ==================================================================================================================== #
# Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany # # Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany #
# # # #
# Licensed under the Apache License, Version 2.0 (the "License"); # # Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. # # you may not use this file except in compliance with the License. #

View File

@@ -71,7 +71,7 @@ data = {
"ubuntu": {"icon": "🐧", "runs-on": "ubuntu-24.04", "shell": "bash", "name": "Linux (x86-64)"}, "ubuntu": {"icon": "🐧", "runs-on": "ubuntu-24.04", "shell": "bash", "name": "Linux (x86-64)"},
"windows": {"icon": "🪟", "runs-on": "windows-latest", "shell": "pwsh", "name": "Windows (x86-64)"}, "windows": {"icon": "🪟", "runs-on": "windows-latest", "shell": "pwsh", "name": "Windows (x86-64)"},
"macos": {"icon": "🍎", "runs-on": "macos-latest-large", "shell": "bash", "name": "macOS (x86-64)"}, "macos": {"icon": "🍎", "runs-on": "macos-latest-large", "shell": "bash", "name": "macOS (x86-64)"},
"macos-arm": {"icon": "🍏", "runs-on": "macos-latest", "shell": "bash", "name": "macOS (arm64)"}, "macos-arm": {"icon": "🍏", "runs-on": "macos-latest", "shell": "bash", "name": "macOS (aarch64)"},
}, },
# Runtimes provided by MSYS2 # Runtimes provided by MSYS2
"runtime": { "runtime": {

View File

@@ -5,9 +5,9 @@ Coverage ~= 7.6
# Test Runner # Test Runner
pytest ~= 8.3 pytest ~= 8.3
pytest-cov ~= 5.0 pytest-cov ~= 6.0
# Static Type Checking # Static Type Checking
mypy ~= 1.11 mypy ~= 1.15
typing_extensions ~= 4.12 typing_extensions ~= 4.12
lxml ~= 5.3 lxml ~= 5.3

View File

@@ -11,7 +11,7 @@
# # # #
# License: # # License: #
# ==================================================================================================================== # # ==================================================================================================================== #
# Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany # # Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany #
# # # #
# Licensed under the Apache License, Version 2.0 (the "License"); # # Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. # # you may not use this file except in compliance with the License. #

View File

@@ -11,7 +11,7 @@
# # # #
# License: # # License: #
# ==================================================================================================================== # # ==================================================================================================================== #
# Copyright 2017-2024 Patrick Lehmann - Bötzingen, Germany # # Copyright 2017-2025 Patrick Lehmann - Bötzingen, Germany #
# # # #
# Licensed under the Apache License, Version 2.0 (the "License"); # # Licensed under the Apache License, Version 2.0 (the "License"); #
# you may not use this file except in compliance with the License. # # you may not use this file except in compliance with the License. #