dbrownell-Common 0.14.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dbrownell_common-0.14.7/.copier-answers.yml +22 -0
- dbrownell_common-0.14.7/.github/CODEOWNERS +1 -0
- dbrownell_common-0.14.7/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- dbrownell_common-0.14.7/.github/ISSUE_TEMPLATE/config.yml +1 -0
- dbrownell_common-0.14.7/.github/ISSUE_TEMPLATE/custom.md +8 -0
- dbrownell_common-0.14.7/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- dbrownell_common-0.14.7/.github/actions/release_impl/action.yml +117 -0
- dbrownell_common-0.14.7/.github/pull_request_template.md +8 -0
- dbrownell_common-0.14.7/.github/release_sources.yaml +6 -0
- dbrownell_common-0.14.7/.github/workflows/CICD.yml +38 -0
- dbrownell_common-0.14.7/.github/workflows/CICD_impl.yml +258 -0
- dbrownell_common-0.14.7/.github/workflows/codeql.yml +87 -0
- dbrownell_common-0.14.7/.gitignore +21 -0
- dbrownell_common-0.14.7/.pre-commit-config.yaml +26 -0
- dbrownell_common-0.14.7/.python-version +1 -0
- dbrownell_common-0.14.7/CODE_OF_CONDUCT.md +43 -0
- dbrownell_common-0.14.7/CONTRIBUTING.md +26 -0
- dbrownell_common-0.14.7/DEVELOPMENT.md +28 -0
- dbrownell_common-0.14.7/GOVERNANCE.md +3 -0
- dbrownell_common-0.14.7/LICENSE +21 -0
- dbrownell_common-0.14.7/MAINTAINERS.md +37 -0
- dbrownell_common-0.14.7/PKG-INFO +95 -0
- dbrownell_common-0.14.7/README.md +62 -0
- dbrownell_common-0.14.7/SECURITY.md +29 -0
- dbrownell_common-0.14.7/minisign_key.pub +2 -0
- dbrownell_common-0.14.7/pyproject.toml +92 -0
- dbrownell_common-0.14.7/src/AutoGitSemVer.yaml +8 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/ContextlibEx.py +31 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/ExecuteTasks.py +1465 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/InflectEx.py +20 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/PathEx.py +222 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/Streams/Capabilities.py +356 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/Streams/DoneManager.py +983 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/Streams/StreamDecorator.py +398 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/Streams/TextWriter.py +47 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/Streams/__init__.py +0 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/SubprocessEx.py +471 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/TestHelpers/StreamTestHelpers.py +167 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/TestHelpers/__init__.py +0 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/TextwrapEx.py +442 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/TyperEx.py +684 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/Types.py +89 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/__init__.py +8 -0
- dbrownell_common-0.14.7/src/dbrownell_Common/py.typed +0 -0
- dbrownell_common-0.14.7/tests/ContextlibEx_UnitTest.py +75 -0
- dbrownell_common-0.14.7/tests/ExecuteTasks_TestManual.py +258 -0
- dbrownell_common-0.14.7/tests/ExecuteTasks_UnitTest.py +332 -0
- dbrownell_common-0.14.7/tests/InflectEx_UnitTest.py +22 -0
- dbrownell_common-0.14.7/tests/PathEx_UnitTest.py +186 -0
- dbrownell_common-0.14.7/tests/Streams/Capabilities_UnitTest.py +115 -0
- dbrownell_common-0.14.7/tests/Streams/DoneManager_UnitTest.py +1587 -0
- dbrownell_common-0.14.7/tests/Streams/StreamDecorator_UnitTest.py +421 -0
- dbrownell_common-0.14.7/tests/Streams/TextWriter_UnitTest.py +46 -0
- dbrownell_common-0.14.7/tests/SubprocessEx_UnitTest.py +219 -0
- dbrownell_common-0.14.7/tests/TestHelpers/StreamTestHelpers_UnitTest.py +254 -0
- dbrownell_common-0.14.7/tests/TextwrapEx_UnitTest.py +356 -0
- dbrownell_common-0.14.7/tests/TyperEx_UnitTest.py +386 -0
- dbrownell_common-0.14.7/tests/Types_UnitTest.py +63 -0
- dbrownell_common-0.14.7/uv.lock +724 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changes here will be overwritten by Copier; DO NOT MODIFY THIS FILE DIRECTLY!
|
|
2
|
+
#
|
|
3
|
+
# This file was generated using copier (https://copier.readthedocs.io/) with the
|
|
4
|
+
# template copier-UvScaffolding (https://github.com/gt-sse-center/copier-UvScaffolding).
|
|
5
|
+
# Additional information (including instructions on how to use this template with copier) is
|
|
6
|
+
# available at https://github.com/gt-sse-center/copier-UvScaffolding.
|
|
7
|
+
#
|
|
8
|
+
|
|
9
|
+
_commit: v0.2.0
|
|
10
|
+
_src_path: .
|
|
11
|
+
author_email: github@DavidBrownell.com
|
|
12
|
+
author_name: David Brownell
|
|
13
|
+
coverage_badge_gist_id: f15146b1b8fdc0a5d45ac0eb786a84f7
|
|
14
|
+
coverage_badge_gist_username: davidbrownell
|
|
15
|
+
github_host: https://github.com
|
|
16
|
+
github_repo_name: dbrownell_Common
|
|
17
|
+
github_username: davidbrownell
|
|
18
|
+
license: MIT
|
|
19
|
+
project_name: dbrownell_Common
|
|
20
|
+
python_package_name: dbrownell_Common
|
|
21
|
+
python_versions: 3.10, 3.11, 3.12, 3.13
|
|
22
|
+
sign_artifacts_question: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @davidbrownell
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a report to help us improve.
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Describe the bug
|
|
11
|
+
A clear and concise description of what the bug is.
|
|
12
|
+
|
|
13
|
+
## To Reproduce
|
|
14
|
+
Steps to reproduce the behavior:
|
|
15
|
+
1. Go to '...'
|
|
16
|
+
2. Click on '....'
|
|
17
|
+
3. Scroll down to '....'
|
|
18
|
+
4. See error
|
|
19
|
+
|
|
20
|
+
## Expected behavior
|
|
21
|
+
A clear and concise description of what you expected to happen.
|
|
22
|
+
|
|
23
|
+
## Screenshots
|
|
24
|
+
If applicable, add screenshots to help explain your problem.
|
|
25
|
+
|
|
26
|
+
## Environment (please complete the following information):
|
|
27
|
+
- OS: [e.g. iOS]
|
|
28
|
+
- Python Version: [e.g. 3.13, 3.12, 3.11, etc.]
|
|
29
|
+
- dbrownell_DevTools Version [e.g. 1.2.3]
|
|
30
|
+
|
|
31
|
+
## Additional context
|
|
32
|
+
Add any other context about the problem here.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
blank_issues_enabled: false
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest an idea for this project.
|
|
4
|
+
title: ''
|
|
5
|
+
labels: ''
|
|
6
|
+
assignees: ''
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Is your feature request related to a problem? Please describe.
|
|
11
|
+
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
12
|
+
|
|
13
|
+
## Describe the solution you'd like
|
|
14
|
+
A clear and concise description of what you want to happen.
|
|
15
|
+
|
|
16
|
+
## Describe alternatives you've considered
|
|
17
|
+
A clear and concise description of any alternative solutions or features you've considered.
|
|
18
|
+
|
|
19
|
+
## Additional context
|
|
20
|
+
Add any other context or screenshots about the feature request here.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
name: "[impl] Release"
|
|
2
|
+
description: "Releases the current repository."
|
|
3
|
+
|
|
4
|
+
# spell-checker: words jedisct, minisig, minisign, pypi, schneegans
|
|
5
|
+
|
|
6
|
+
inputs:
|
|
7
|
+
minisign_private_key:
|
|
8
|
+
description: "Key used to sign dist artifacts. No signatures will be created if the key is empty."
|
|
9
|
+
required: false
|
|
10
|
+
default: ""
|
|
11
|
+
|
|
12
|
+
pypi_publish_token:
|
|
13
|
+
description: "Token used to publish the package to PyPI."
|
|
14
|
+
required: false
|
|
15
|
+
default: ""
|
|
16
|
+
|
|
17
|
+
coverage_badge_gist_token:
|
|
18
|
+
description: "Gist token used to store the code coverage badge."
|
|
19
|
+
default: ""
|
|
20
|
+
|
|
21
|
+
coverage_badge_gist_id:
|
|
22
|
+
description: "Gist ID used to store the code coverage badge."
|
|
23
|
+
required: false
|
|
24
|
+
default: ""
|
|
25
|
+
|
|
26
|
+
coverage_badge_gist_username:
|
|
27
|
+
description: "Gist username used to store the code coverage badge. The current GitHub user will be used if this value is not provided."
|
|
28
|
+
required: false
|
|
29
|
+
default: ""
|
|
30
|
+
|
|
31
|
+
runs:
|
|
32
|
+
using: composite
|
|
33
|
+
steps:
|
|
34
|
+
- name: Install uv and python
|
|
35
|
+
uses: astral-sh/setup-uv@v5
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: false # No uv.lock or requirements.txt files, so nothing to cache on
|
|
38
|
+
|
|
39
|
+
- name: Download Python Package
|
|
40
|
+
uses: actions/download-artifact@v4
|
|
41
|
+
with:
|
|
42
|
+
name: Python package
|
|
43
|
+
path: dist
|
|
44
|
+
|
|
45
|
+
# Create repository tag
|
|
46
|
+
- name: Create Repository Tag
|
|
47
|
+
shell: bash
|
|
48
|
+
run: |-
|
|
49
|
+
git config user.name "GitHub Action Bot"
|
|
50
|
+
git config user.email "<>"
|
|
51
|
+
|
|
52
|
+
git tag --annotate --force -m "Publish Tag" "v${{ env.PACKAGE_VERSION }}" "${{ github.sha }}"
|
|
53
|
+
git push origin "v${{ env.PACKAGE_VERSION }}" --force
|
|
54
|
+
|
|
55
|
+
# Commit code coverage
|
|
56
|
+
- name: Create Code Coverage Badge
|
|
57
|
+
if: ${{ inputs.coverage_badge_gist_token != '' && inputs.coverage_badge_gist_id != '' }}
|
|
58
|
+
uses: schneegans/dynamic-badges-action@v1.7.0
|
|
59
|
+
with:
|
|
60
|
+
auth: ${{ inputs.coverage_badge_gist_token }}
|
|
61
|
+
gistID: ${{ inputs.coverage_badge_gist_id }}
|
|
62
|
+
filename: ${{ github.event.repository.name }}_code_coverage.json
|
|
63
|
+
label: Coverage
|
|
64
|
+
message: ${{ env.COVERAGE_TOTAL }}%
|
|
65
|
+
valColorRange: ${{ env.COVERAGE_TOTAL }}
|
|
66
|
+
minColorRange: 50
|
|
67
|
+
maxColorRange: 90
|
|
68
|
+
|
|
69
|
+
- name: Display Code Coverage Badge Url
|
|
70
|
+
if: ${{ inputs.coverage_badge_gist_token != '' && inputs.coverage_badge_gist_id != '' }}
|
|
71
|
+
shell: bash
|
|
72
|
+
run: |-
|
|
73
|
+
username="${{ inputs.coverage_badge_gist_username }}"
|
|
74
|
+
if [ -z "${username}" ]; then
|
|
75
|
+
username="${{ github.repository_owner }}"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
echo "**Code Coverage Badge:** [](${{ github.server_url }}/${{ github.repository_owner }}/${{ github.event.repository.name }}/actions)" >> $GITHUB_STEP_SUMMARY
|
|
79
|
+
echo "**Code Coverage Badge Markdown:** <code>\[!\[Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${username}/${{ inputs.coverage_badge_gist_id }}/raw/${{ github.event.repository.name }}_code_coverage.json)](${{ github.server_url }}/${{ github.repository_owner }}/${{ github.event.repository.name }}/actions)</code>" >> $GITHUB_STEP_SUMMARY
|
|
80
|
+
|
|
81
|
+
# Sign artifacts
|
|
82
|
+
- name: Sign Artifacts
|
|
83
|
+
if: ${{ inputs.minisign_private_key != '' }}
|
|
84
|
+
shell: bash
|
|
85
|
+
run: |-
|
|
86
|
+
pushd dist
|
|
87
|
+
|
|
88
|
+
echo "**Signed Artifacts:**" >> $GITHUB_STEP_SUMMARY
|
|
89
|
+
|
|
90
|
+
echo "${{ inputs.minisign_private_key }}" > /tmp/minisign.key
|
|
91
|
+
|
|
92
|
+
for filename in *; do
|
|
93
|
+
echo "- ${filename} [${filename}.minisig]" >> $GITHUB_STEP_SUMMARY
|
|
94
|
+
uv run --with py-minisign python -c "import minisign; minisign.SecretKey.from_file('/tmp/minisign.key').sign_file('${filename}', trusted_comment='${{ env.PACKAGE_NAME }} v${{ env.PACKAGE_VERSION }}', drop_signature=True)"
|
|
95
|
+
done
|
|
96
|
+
|
|
97
|
+
rm /tmp/minisign.key
|
|
98
|
+
|
|
99
|
+
- name: Upload Signatures
|
|
100
|
+
if: ${{ inputs.minisign_private_key != '' }}
|
|
101
|
+
uses: actions/upload-artifact@v4
|
|
102
|
+
with:
|
|
103
|
+
name: Minisign signatures
|
|
104
|
+
path: ./dist/*.minisig
|
|
105
|
+
|
|
106
|
+
# Create the GitHub release
|
|
107
|
+
- name: Create GitHub Release
|
|
108
|
+
shell: bash
|
|
109
|
+
run: |-
|
|
110
|
+
gh release create "v${{ env.PACKAGE_VERSION }}" ./dist/* --generate-notes
|
|
111
|
+
|
|
112
|
+
# Publish Python Package
|
|
113
|
+
- name: Publish Python Package
|
|
114
|
+
if: ${{ inputs.pypi_publish_token != '' }}
|
|
115
|
+
shell: bash
|
|
116
|
+
run: |-
|
|
117
|
+
uv publish --token "${{ inputs.pypi_publish_token }}" --verbose
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## :pencil: Description
|
|
2
|
+
Please include a summary of the change.
|
|
3
|
+
|
|
4
|
+
## :gear: Work Item
|
|
5
|
+
Please include link to the corresponding GitHub Issue or Project work item.
|
|
6
|
+
|
|
7
|
+
## :movie_camera: Demo
|
|
8
|
+
Please provide any images, GIFs, or videos that show the effect of your changes (if applicable). A picture is worth a thousand words.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: "CI+CD"
|
|
2
|
+
run-name: ${{ github.run_number }} [${{ github.actor }}] on ${{ github.ref_name }}
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
pull_request:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
push:
|
|
9
|
+
branches:
|
|
10
|
+
- main
|
|
11
|
+
schedule:
|
|
12
|
+
- cron: '0 0 * * *' # Once a day at 12am UTC
|
|
13
|
+
workflow_dispatch:
|
|
14
|
+
|
|
15
|
+
permissions: {}
|
|
16
|
+
|
|
17
|
+
jobs:
|
|
18
|
+
CICD_Workflow:
|
|
19
|
+
name: "CI+CD Workflow"
|
|
20
|
+
|
|
21
|
+
permissions:
|
|
22
|
+
contents: write
|
|
23
|
+
|
|
24
|
+
uses: ./.github/workflows/CICD_impl.yml
|
|
25
|
+
|
|
26
|
+
with:
|
|
27
|
+
# These values can be customized for your specific requirements.
|
|
28
|
+
operating_system_json_string: "[ 'macos-latest', 'ubuntu-latest', 'windows-latest' ]"
|
|
29
|
+
python_version_json_string: "['3.13', '3.12', '3.11', '3.10']"
|
|
30
|
+
python_package_version: "3.10"
|
|
31
|
+
coverage_badge_gist_id: "f15146b1b8fdc0a5d45ac0eb786a84f7"
|
|
32
|
+
coverage_badge_gist_username: "davidbrownell"
|
|
33
|
+
|
|
34
|
+
secrets:
|
|
35
|
+
# These values should be populated as GitHub Action secrets (https://github.com/davidbrownell/dbrownell_Common/settings/secrets/actions)
|
|
36
|
+
MINISIGN_PRIVATE_KEY: ${{ secrets.MINISIGN_PRIVATE_KEY }}
|
|
37
|
+
PYPI_PUBLISH_TOKEN: ${{ secrets.PYPI_PUBLISH_TOKEN }}
|
|
38
|
+
COVERAGE_BADGE_GIST_TOKEN: ${{ secrets.COVERAGE_BADGE_GIST_TOKEN }}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
name: "[Callable] CI+CD Workflow Impl"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_call:
|
|
5
|
+
inputs:
|
|
6
|
+
operating_system_json_string:
|
|
7
|
+
type: string
|
|
8
|
+
description: "The operating systems to run the job on. Note that this is JSON content embedded within a string."
|
|
9
|
+
required: true
|
|
10
|
+
|
|
11
|
+
python_version_json_string:
|
|
12
|
+
type: string
|
|
13
|
+
description: "The Python versions to run the job with. Note that this is JSON content embedded within a string."
|
|
14
|
+
required: true
|
|
15
|
+
|
|
16
|
+
python_package_version:
|
|
17
|
+
type: string
|
|
18
|
+
description: "The python version used when creating the python package."
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
coverage_badge_gist_id:
|
|
22
|
+
type: string
|
|
23
|
+
description: "The ID of the Gist used to store coverage badge information. Code coverage information will not be persisted if this value is missing."
|
|
24
|
+
required: false
|
|
25
|
+
|
|
26
|
+
coverage_badge_gist_username:
|
|
27
|
+
type: string
|
|
28
|
+
description: "The username used to access the Gist used to store coverage badge information. The current GitHub user will be used if this value is not provided."
|
|
29
|
+
required: false
|
|
30
|
+
|
|
31
|
+
secrets:
|
|
32
|
+
MINISIGN_PRIVATE_KEY:
|
|
33
|
+
required: false
|
|
34
|
+
description: "Private key used to sign artifacts. Artifacts will not be signed if this value is missing."
|
|
35
|
+
|
|
36
|
+
PYPI_PUBLISH_TOKEN:
|
|
37
|
+
required: false
|
|
38
|
+
description: "Token used to publish packages to PyPi. Packages will not be published if this value is missing."
|
|
39
|
+
|
|
40
|
+
COVERAGE_BADGE_GIST_TOKEN:
|
|
41
|
+
required: false
|
|
42
|
+
description: "Token used to access the Gist used to store coverage badge information. Code coverage information will not be persisted if this value is missing."
|
|
43
|
+
|
|
44
|
+
jobs:
|
|
45
|
+
# ----------------------------------------------------------------------
|
|
46
|
+
validate:
|
|
47
|
+
strategy:
|
|
48
|
+
fail-fast: false
|
|
49
|
+
|
|
50
|
+
matrix:
|
|
51
|
+
os: ${{ fromJson(inputs.operating_system_json_string) }}
|
|
52
|
+
python_version: ${{ fromJson(inputs.python_version_json_string) }}
|
|
53
|
+
|
|
54
|
+
name: Validate
|
|
55
|
+
runs-on: ${{ matrix.os }}
|
|
56
|
+
|
|
57
|
+
permissions:
|
|
58
|
+
contents: read
|
|
59
|
+
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v4
|
|
62
|
+
|
|
63
|
+
- name: Install uv and python
|
|
64
|
+
uses: astral-sh/setup-uv@v5
|
|
65
|
+
with:
|
|
66
|
+
python-version: ${{ matrix.python_version }}
|
|
67
|
+
enable-cache: true
|
|
68
|
+
|
|
69
|
+
- name: Run pre-commit scripts
|
|
70
|
+
run: uv run pre-commit run --verbose
|
|
71
|
+
|
|
72
|
+
- name: Validate Tests
|
|
73
|
+
run: uv run pytest
|
|
74
|
+
env:
|
|
75
|
+
COVERAGE_FILE: .coverage.${{ matrix.os }}.${{ matrix.python_version }}
|
|
76
|
+
|
|
77
|
+
- name: Upload Coverage Data
|
|
78
|
+
uses: actions/upload-artifact@v4
|
|
79
|
+
with:
|
|
80
|
+
name: .coverage.${{ matrix.os }}.${{ matrix.python_version }}
|
|
81
|
+
path: .coverage.${{ matrix.os }}.${{ matrix.python_version }}
|
|
82
|
+
include-hidden-files: true
|
|
83
|
+
|
|
84
|
+
# ----------------------------------------------------------------------
|
|
85
|
+
package_coverage:
|
|
86
|
+
needs: validate
|
|
87
|
+
|
|
88
|
+
name: Postprocess Coverage Info
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
|
|
91
|
+
outputs:
|
|
92
|
+
coverage_total: ${{ steps.combine_coverage_data.outputs.coverage_total }}
|
|
93
|
+
|
|
94
|
+
permissions:
|
|
95
|
+
contents: read
|
|
96
|
+
|
|
97
|
+
steps:
|
|
98
|
+
- uses: actions/checkout@v4
|
|
99
|
+
|
|
100
|
+
- name: Install uv and python
|
|
101
|
+
uses: astral-sh/setup-uv@v5
|
|
102
|
+
with:
|
|
103
|
+
enable-cache: true
|
|
104
|
+
|
|
105
|
+
- name: Install Dependencies
|
|
106
|
+
run: uv sync --frozen
|
|
107
|
+
|
|
108
|
+
- name: Download Coverage Data
|
|
109
|
+
uses: actions/download-artifact@v4
|
|
110
|
+
with:
|
|
111
|
+
merge-multiple: true
|
|
112
|
+
|
|
113
|
+
- name: Combine Coverage Data
|
|
114
|
+
id: combine_coverage_data
|
|
115
|
+
shell: bash
|
|
116
|
+
run: |
|
|
117
|
+
uv run coverage combine .
|
|
118
|
+
uv run coverage report --ignore-errors --show-missing --skip-covered
|
|
119
|
+
uv run coverage json --ignore-errors -o .coverage.json
|
|
120
|
+
|
|
121
|
+
export TOTAL=$(uv run python -c "import json;print(json.load(open('.coverage.json'))['totals']['percent_covered_display'])")
|
|
122
|
+
echo "coverage_total=${TOTAL}" >> $GITHUB_OUTPUT
|
|
123
|
+
echo "**Total coverage:** ${TOTAL}%" >> $GITHUB_STEP_SUMMARY
|
|
124
|
+
|
|
125
|
+
- name: Upload Coverage Data
|
|
126
|
+
uses: actions/upload-artifact@v4
|
|
127
|
+
with:
|
|
128
|
+
name: .coverage.json
|
|
129
|
+
path: .coverage.json
|
|
130
|
+
include-hidden-files: true
|
|
131
|
+
|
|
132
|
+
# ----------------------------------------------------------------------
|
|
133
|
+
python_package:
|
|
134
|
+
needs: package_coverage
|
|
135
|
+
|
|
136
|
+
name: Build Python Package
|
|
137
|
+
runs-on: ubuntu-latest
|
|
138
|
+
|
|
139
|
+
outputs:
|
|
140
|
+
package_name: ${{ steps.package_name_and_version.outputs.package_name }}
|
|
141
|
+
package_version: ${{ steps.package_name_and_version.outputs.package_version }}
|
|
142
|
+
|
|
143
|
+
permissions:
|
|
144
|
+
contents: read
|
|
145
|
+
|
|
146
|
+
steps:
|
|
147
|
+
- uses: actions/checkout@v4
|
|
148
|
+
with:
|
|
149
|
+
fetch-depth: 0
|
|
150
|
+
|
|
151
|
+
- name: Install uv and python
|
|
152
|
+
uses: astral-sh/setup-uv@v5
|
|
153
|
+
with:
|
|
154
|
+
enable-cache: true
|
|
155
|
+
python-version: ${{ inputs.python_package_version }}
|
|
156
|
+
|
|
157
|
+
- name: Install Dependencies
|
|
158
|
+
run: uv sync --frozen
|
|
159
|
+
|
|
160
|
+
- name: Update Version
|
|
161
|
+
run: uv run python -m AutoGitSemVer.scripts.UpdatePythonVersion ./src/dbrownell_Common/__init__.py ./src --verbose
|
|
162
|
+
|
|
163
|
+
- name: Build Python Package
|
|
164
|
+
run: uv build
|
|
165
|
+
|
|
166
|
+
- name: Save Package Name and Version
|
|
167
|
+
id: package_name_and_version
|
|
168
|
+
run: |-
|
|
169
|
+
cd dist
|
|
170
|
+
|
|
171
|
+
export PACKAGE_NAME=$(ls *.whl)
|
|
172
|
+
echo "package_name=${PACKAGE_NAME}" >> $GITHUB_OUTPUT
|
|
173
|
+
echo "**Package Name:** ${PACKAGE_NAME}" >> $GITHUB_STEP_SUMMARY
|
|
174
|
+
|
|
175
|
+
export PACKAGE_VERSION=$(uv run python -c "import dbrownell_Common as package; print(package.__version__)")
|
|
176
|
+
echo "package_version=${PACKAGE_VERSION}" >> $GITHUB_OUTPUT
|
|
177
|
+
echo "**Package Version:** ${PACKAGE_VERSION}" >> $GITHUB_STEP_SUMMARY
|
|
178
|
+
|
|
179
|
+
- name: Upload Python Package
|
|
180
|
+
uses: actions/upload-artifact@v4
|
|
181
|
+
with:
|
|
182
|
+
name: Python package
|
|
183
|
+
path: dist/**
|
|
184
|
+
|
|
185
|
+
# ----------------------------------------------------------------------
|
|
186
|
+
validate_python_package:
|
|
187
|
+
needs: python_package
|
|
188
|
+
|
|
189
|
+
strategy:
|
|
190
|
+
fail-fast: false
|
|
191
|
+
|
|
192
|
+
matrix:
|
|
193
|
+
os: ${{ fromJson(inputs.operating_system_json_string) }}
|
|
194
|
+
python_version: ${{ fromJson(inputs.python_version_json_string) }}
|
|
195
|
+
|
|
196
|
+
name: Validate Python Package
|
|
197
|
+
runs-on: ${{ matrix.os }}
|
|
198
|
+
|
|
199
|
+
env:
|
|
200
|
+
PACKAGE_NAME: ${{ needs.python_package.outputs.package_name }}
|
|
201
|
+
PACKAGE_VERSION: ${{ needs.python_package.outputs.package_version }}
|
|
202
|
+
|
|
203
|
+
permissions: {}
|
|
204
|
+
|
|
205
|
+
steps:
|
|
206
|
+
- name: Install uv and python
|
|
207
|
+
uses: astral-sh/setup-uv@v5
|
|
208
|
+
with:
|
|
209
|
+
python-version: ${{ matrix.python_version }}
|
|
210
|
+
enable-cache: false # No uv.lock or requirements.txt files, so nothing to cache on
|
|
211
|
+
ignore-empty-workdir: true
|
|
212
|
+
|
|
213
|
+
- name: Download Python Package
|
|
214
|
+
uses: actions/download-artifact@v4
|
|
215
|
+
with:
|
|
216
|
+
name: Python package
|
|
217
|
+
path: dist
|
|
218
|
+
|
|
219
|
+
- name: Install Python Package
|
|
220
|
+
run: uv pip install dist/${{ env.PACKAGE_NAME }}
|
|
221
|
+
|
|
222
|
+
- name: Validate Python Package
|
|
223
|
+
run: uv run python -c "import dbrownell_Common as package; assert package.__version__ == '${{ env.PACKAGE_VERSION }}', package.__version__"
|
|
224
|
+
|
|
225
|
+
# ----------------------------------------------------------------------
|
|
226
|
+
release:
|
|
227
|
+
needs: [package_coverage, python_package, validate_python_package]
|
|
228
|
+
|
|
229
|
+
name: Release
|
|
230
|
+
runs-on: ubuntu-latest
|
|
231
|
+
|
|
232
|
+
env:
|
|
233
|
+
COVERAGE_TOTAL: ${{ needs.package_coverage.outputs.coverage_total }}
|
|
234
|
+
PACKAGE_NAME: ${{ needs.python_package.outputs.package_name }}
|
|
235
|
+
PACKAGE_VERSION: ${{ needs.python_package.outputs.package_version }}
|
|
236
|
+
GH_TOKEN: ${{ github.token }}
|
|
237
|
+
|
|
238
|
+
permissions:
|
|
239
|
+
contents: write # To tag the repository and create the release
|
|
240
|
+
|
|
241
|
+
steps:
|
|
242
|
+
- uses: actions/checkout@v4
|
|
243
|
+
|
|
244
|
+
- name: Has Release Changes?
|
|
245
|
+
id: has_release_changes
|
|
246
|
+
uses: dorny/paths-filter@v3
|
|
247
|
+
with:
|
|
248
|
+
filters: ./.github/release_sources.yaml
|
|
249
|
+
|
|
250
|
+
- name: Release
|
|
251
|
+
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && steps.has_release_changes.outputs.src == 'true' }}
|
|
252
|
+
uses: ./.github/actions/release_impl
|
|
253
|
+
with:
|
|
254
|
+
minisign_private_key: ${{ secrets.MINISIGN_PRIVATE_KEY }}
|
|
255
|
+
pypi_publish_token: ${{ secrets.PYPI_PUBLISH_TOKEN }}
|
|
256
|
+
coverage_badge_gist_token: ${{ secrets.COVERAGE_BADGE_GIST_TOKEN }}
|
|
257
|
+
coverage_badge_gist_id: ${{ inputs.coverage_badge_gist_id }}
|
|
258
|
+
coverage_badge_gist_username: ${{ inputs.coverage_badge_gist_username }}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
|
2
|
+
# to commit it to your repository.
|
|
3
|
+
#
|
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
|
5
|
+
# or to provide custom queries or build logic.
|
|
6
|
+
#
|
|
7
|
+
# ******** NOTE ********
|
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
|
10
|
+
# supported CodeQL languages.
|
|
11
|
+
#
|
|
12
|
+
name: "CodeQL"
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [ "main" ]
|
|
17
|
+
pull_request:
|
|
18
|
+
branches: [ "main" ]
|
|
19
|
+
schedule:
|
|
20
|
+
- cron: '0 0 * * *'
|
|
21
|
+
workflow_dispatch:
|
|
22
|
+
|
|
23
|
+
permissions: {}
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
analyze:
|
|
27
|
+
name: Analyze
|
|
28
|
+
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
29
|
+
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
30
|
+
# - https://gh.io/supported-runners-and-hardware-resources
|
|
31
|
+
# - https://gh.io/using-larger-runners
|
|
32
|
+
# Consider using larger runners for possible analysis time improvements.
|
|
33
|
+
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
34
|
+
timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
|
|
35
|
+
permissions:
|
|
36
|
+
# required for all workflows
|
|
37
|
+
security-events: write
|
|
38
|
+
|
|
39
|
+
# only required for workflows in private repositories
|
|
40
|
+
actions: read
|
|
41
|
+
contents: read
|
|
42
|
+
|
|
43
|
+
strategy:
|
|
44
|
+
fail-fast: false
|
|
45
|
+
matrix:
|
|
46
|
+
language: [ 'python' ]
|
|
47
|
+
# CodeQL supports [ 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift' ]
|
|
48
|
+
# Use only 'java-kotlin' to analyze code written in Java, Kotlin or both
|
|
49
|
+
# Use only 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
|
50
|
+
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- name: Checkout repository
|
|
54
|
+
uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
# Initializes the CodeQL tools for scanning.
|
|
57
|
+
- name: Initialize CodeQL
|
|
58
|
+
uses: github/codeql-action/init@v3
|
|
59
|
+
with:
|
|
60
|
+
languages: ${{ matrix.language }}
|
|
61
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
62
|
+
# By default, queries listed here will override any specified in a config file.
|
|
63
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
64
|
+
|
|
65
|
+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
66
|
+
# queries: security-extended,security-and-quality
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
|
|
70
|
+
# If this step fails, then you should remove it and run the build manually (see below)
|
|
71
|
+
- name: Autobuild
|
|
72
|
+
uses: github/codeql-action/autobuild@v3
|
|
73
|
+
|
|
74
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
|
75
|
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
76
|
+
|
|
77
|
+
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
|
78
|
+
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
|
79
|
+
|
|
80
|
+
# - run: |
|
|
81
|
+
# echo "Run, Build Application using script"
|
|
82
|
+
# ./location_of_script_within_repo/buildscript.sh
|
|
83
|
+
|
|
84
|
+
- name: Perform CodeQL Analysis
|
|
85
|
+
uses: github/codeql-action/analyze@v3
|
|
86
|
+
with:
|
|
87
|
+
category: "/language:${{matrix.language}}"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
post_generation_actions.html
|
|
2
|
+
|
|
3
|
+
Activate*.cmd
|
|
4
|
+
Activate*.sh
|
|
5
|
+
Deactivate*.cmd
|
|
6
|
+
Deactivate*.sh
|
|
7
|
+
|
|
8
|
+
**/__pycache__/**
|
|
9
|
+
**/Generated/**
|
|
10
|
+
|
|
11
|
+
**/.coverage
|
|
12
|
+
**/lcov.info
|
|
13
|
+
**/.vscode
|
|
14
|
+
|
|
15
|
+
build/**
|
|
16
|
+
dist/**
|
|
17
|
+
src/dbrownell_Common.egg-info/**
|
|
18
|
+
|
|
19
|
+
minisign_key.pri
|
|
20
|
+
.DS_Store
|
|
21
|
+
post_generation_instructions.html
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# See https://pre-commit.com for more information
|
|
2
|
+
# See https://pre-commit.com/hooks.html for more hooks
|
|
3
|
+
repos:
|
|
4
|
+
- repo: local
|
|
5
|
+
hooks:
|
|
6
|
+
- id: uv sync --frozen
|
|
7
|
+
name: uv sync --frozen
|
|
8
|
+
entry: uv sync --frozen
|
|
9
|
+
language: system
|
|
10
|
+
pass_filenames: false
|
|
11
|
+
require_serial: true
|
|
12
|
+
always_run: true
|
|
13
|
+
|
|
14
|
+
- id: uv run ruff format --check
|
|
15
|
+
name: uv run ruff format --check
|
|
16
|
+
entry: uv run ruff format --check
|
|
17
|
+
language: system
|
|
18
|
+
pass_filenames: false
|
|
19
|
+
always_run: true
|
|
20
|
+
|
|
21
|
+
- id: uv run ruff check
|
|
22
|
+
name: uv run ruff check
|
|
23
|
+
entry: uv run ruff check
|
|
24
|
+
language: system
|
|
25
|
+
pass_filenames: false
|
|
26
|
+
always_run: true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|